TypeScript Version: 3.4.0@rc
Search Terms:
Code
export type Prop<T> = { (): T }
export type PropType<T> = Prop<T>;
export type PropDefaultValue<T> = T;
export type PropValidatorFunction<T> = (value: T) => boolean;
export type PropValidator<T> = PropOptions<T>;
export type PropOptions<T> = {
type: PropType<T>;
value?: PropDefaultValue<T>,
required?: boolean;
validator?: PropValidatorFunction<T>;
}
export type RecordPropsDefinition<T> = {
[K in keyof T]: PropValidator<T[K]>
}
export type PropsDefinition<T> = RecordPropsDefinition<T>;
declare function extend<T>({ props }: { props: PropsDefinition<T> }): PropsDefinition<T>;
interface MyType {
valid: boolean;
}
const r = extend({
props: {
// gets resolved to PropOptions<any> but should be PropType<MyType>
notResolved: {
type: Object as PropType<MyType>,
// type not inferred
validator: (x) => {
return x.valid;
}
},
// gets resolved currectly to PropType<MyType>
// on [email protected] doest resolve to PropType<MyType>
explicit: {
type: Object as PropType<MyType>,
// type not inferred
validator: (x: MyType) => {
return x.valid;
}
}
}
})
// return type on 3.4@rc doesn't get resolved
r.explicit
r.notResolved
r.explicit.required
r.notResolved.required
Expected behavior:
The validator parameter as typescript type inferred from T.
Props record values to be resolved with the interface of PropType
Return type to be PropsDefinition<T>
Actual behavior:
Getting validator parameter resolved as any/unknown.
Record types are not getting resolve to the type PropOptions<T> in 3.4@rc but working in 3.3.x
The return type not working in 3.4@rc
Playground Link:
playground
This hasn't worked particularly well in any version, but this seems to be regressing:
type Box<T> = {
contents: T;
contains?(content: T): boolean;
};
type Mapped<T> = {
[K in keyof T]: Box<T[K]>;
}
declare function id<T>(arg: Mapped<T>): Mapped<T>;
// obj1: Mapped<{ foo: string }> β
const obj1 = id({
foo: {
contents: ""
}
});
// 3.3 obj2: Mapped<{ foo: any }> β
// 3.4 obj2: Mapped<{}> ββ
const obj2 = id({
foo: {
contents: "",
// k: implicit any β
contains(k) {
return k.length > 0;
}
}
});
The key issue here is that during the initial pass in type inference where we defer context sensitive function expressions and arrow functions, we never perform reverse mapped type inference on types that contain anything context sensitive. That is too conservative because, as illustrated by the examples, there are cases where we want to infer from the properties that aren't context sensitive and then apply those inferences to the context sensitive locations. I will be putting up a PR that does this.
Most helpful comment
The key issue here is that during the initial pass in type inference where we defer context sensitive function expressions and arrow functions, we never perform reverse mapped type inference on types that contain anything context sensitive. That is too conservative because, as illustrated by the examples, there are cases where we want to infer from the properties that aren't context sensitive and then apply those inferences to the context sensitive locations. I will be putting up a PR that does this.