-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Description
Bug Report
π Search Terms
conditional-type, distributive-type, generics
π Version & Regression Information
Version 4.9.4 and nightly
β― Playground Link
TS resolves type to different type even if I add constraint that should resolve to given type
π» Code
type PrimitiveDataType = string | number | bigint | boolean | symbol | undefined | null;
type ConditionalType<T> = [T] extends [PrimitiveDataType]
? (v: T) => void
: T extends Array<unknown>
? (v: T, t: number) => void
: never;
abstract class AbstractClass<T> {
abstract value: T;
protected conditionalFunctions: Map<ConditionalType<T>, number | undefined> = new Map();
}
class SomeClass<T extends PrimitiveDataType> extends AbstractClass<T> {
value: T;
constructor(value: T) {
super();
this.value = value;
}
someMethod() {
for (const someFn of this.conditionalFunctions.keys()) {
someFn(this.value);
}
}
}
In the above code I have created a PrimitiveDataType
which is a union of all primitive data types in JavaScript. Then I have created a ConditionalType<T>
that will resolve to some callback only if T
is one of PrimitiveDataType
. Then I have created an abstract generic class that have a field which type(ConditionalType<T>
) depends on generic value of this class. In the end, I have crated a SomeClass
that extends AbstractClass<T>
and add constraints that generic parameter T
have to extend PrimitiveDataType
.
π Actual behavior
For someMethod
of this SomeClass
conditionalFunctions.keys()
is resolved to (v: T, t: number) => void
what would implicate that my generic T
extends an Array
type.
π Expected behavior
For someMethod
of this SomeClass
I have expected that TS should resolve conditionalFunctions.keys()
to (v: T) => void
to my surprise it is resolved to (v: T, t: number) => void
what would implicate that my generic T
extends an Array
type. This doesn't make sens to me because T
has constraint that has to extends PrimitiveDataType
.
Example of what I would expect:
type PrimitiveDataType = string | number | bigint | boolean | symbol | undefined | null;
type ConditionalType<T> = [T] extends [PrimitiveDataType]
? (v: T) => void
: T extends Array<unknown>
? (v: T, t: number) => void
: never;
const x: PrimitiveDataType = 12;
const y: ConditionalType<typeof x> = (param: number) => undefined;