Merge pull request #22989 from Microsoft/fixImpliedConstraint

Fix implied constraints in conditional types
This commit is contained in:
Anders Hejlsberg
2018-03-29 17:06:16 -07:00
committed by GitHub
6 changed files with 180 additions and 6 deletions

View File

@@ -7407,7 +7407,7 @@ namespace ts {
function getConstrainedTypeVariable(typeVariable: TypeVariable, node: Node) {
let constraints: Type[];
while (isPartOfTypeNode(node)) {
while (node && !isStatement(node)) {
const parent = node.parent;
if (parent.kind === SyntaxKind.ConditionalType && node === (<ConditionalTypeNode>parent).trueType) {
const constraint = getImpliedConstraint(typeVariable, (<ConditionalTypeNode>parent).checkType, (<ConditionalTypeNode>parent).extendsType);
@@ -8356,17 +8356,17 @@ namespace ts {
// resolution of the conditional type such that a later instantiation will properly distribute
// over union types.
const isDeferred = root.isDistributive && maybeTypeOfKind(checkType, TypeFlags.Instantiable);
let combinedMapper: TypeMapper;
if (root.inferTypeParameters) {
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
let combinedMapper: TypeMapper;
if (root.inferTypeParameters) {
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
if (!isDeferred) {
// We don't want inferences from constraints as they may cause us to eagerly resolve the
// conditional type instead of deferring resolution. Also, we always want strict function
// types rules (i.e. proper contravariance) for inferences.
inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
}
combinedMapper = combineTypeMappers(mapper, context);
}
combinedMapper = combineTypeMappers(mapper, context);
}
if (!isDeferred) {
// Return union of trueType and falseType for 'any' since it matches anything
if (checkType.flags & TypeFlags.Any) {

View File

@@ -501,4 +501,16 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
type Extracted<Struct> = {
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
}
// Repro from #22985
type RecursivePartial<T> = {
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
T[P] extends object ? RecursivePartial<T[P]> : T[P];
};
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})

View File

@@ -339,6 +339,18 @@ declare interface ExtractFooBar<FB extends FooBar> { }
type Extracted<Struct> = {
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
}
// Repro from #22985
type RecursivePartial<T> = {
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
T[P] extends object ? RecursivePartial<T[P]> : T[P];
};
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
//// [conditionalTypes1.js]
@@ -435,6 +447,8 @@ var f45 = function (value) { return value; }; // Error
// Repro from #21863
function f50() {
}
var a = { o: 1, b: 2, c: [{ a: 1, c: '213' }] };
assign(a, { o: 2, c: { 0: { a: 2, c: '213123' } } });
//// [conditionalTypes1.d.ts]
@@ -687,3 +701,17 @@ declare interface ExtractFooBar<FB extends FooBar> {
declare type Extracted<Struct> = {
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
};
declare type RecursivePartial<T> = {
[P in keyof T]?: T[P] extends Array<any> ? {
[index: number]: RecursivePartial<T[P][0]>;
} : T[P] extends object ? RecursivePartial<T[P]> : T[P];
};
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
declare var a: {
o: number;
b: number;
c: {
a: number;
c: string;
}[];
};

View File

@@ -1317,3 +1317,57 @@ type Extracted<Struct> = {
>K : Symbol(K, Decl(conditionalTypes1.ts, 338, 5))
}
// Repro from #22985
type RecursivePartial<T> = {
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>index : Symbol(index, Decl(conditionalTypes1.ts, 344, 47))
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
T[P] extends object ? RecursivePartial<T[P]> : T[P];
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
};
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
>assign : Symbol(assign, Decl(conditionalTypes1.ts, 346, 2))
>T : Symbol(T, Decl(conditionalTypes1.ts, 348, 24))
>o : Symbol(o, Decl(conditionalTypes1.ts, 348, 27))
>T : Symbol(T, Decl(conditionalTypes1.ts, 348, 24))
>a : Symbol(a, Decl(conditionalTypes1.ts, 348, 32))
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
>T : Symbol(T, Decl(conditionalTypes1.ts, 348, 24))
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
>a : Symbol(a, Decl(conditionalTypes1.ts, 350, 3))
>o : Symbol(o, Decl(conditionalTypes1.ts, 350, 9))
>b : Symbol(b, Decl(conditionalTypes1.ts, 350, 14))
>c : Symbol(c, Decl(conditionalTypes1.ts, 350, 20))
>a : Symbol(a, Decl(conditionalTypes1.ts, 350, 26))
>c : Symbol(c, Decl(conditionalTypes1.ts, 350, 31))
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
>assign : Symbol(assign, Decl(conditionalTypes1.ts, 346, 2))
>a : Symbol(a, Decl(conditionalTypes1.ts, 350, 3))
>o : Symbol(o, Decl(conditionalTypes1.ts, 351, 11))
>c : Symbol(c, Decl(conditionalTypes1.ts, 351, 16))
>0 : Symbol(0, Decl(conditionalTypes1.ts, 351, 21))
>a : Symbol(a, Decl(conditionalTypes1.ts, 351, 25))
>c : Symbol(c, Decl(conditionalTypes1.ts, 351, 30))

View File

@@ -1474,3 +1474,71 @@ type Extracted<Struct> = {
>K : K
}
// Repro from #22985
type RecursivePartial<T> = {
>RecursivePartial : RecursivePartial<T>
>T : T
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
>P : P
>T : T
>T : T
>P : P
>Array : T[]
>index : number
>RecursivePartial : RecursivePartial<T>
>T : T
>P : P
T[P] extends object ? RecursivePartial<T[P]> : T[P];
>T : T
>P : P
>RecursivePartial : RecursivePartial<T>
>T : T
>P : P
>T : T
>P : P
};
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
>assign : <T>(o: T, a: RecursivePartial<T>) => void
>T : T
>o : T
>T : T
>a : RecursivePartial<T>
>RecursivePartial : RecursivePartial<T>
>T : T
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
>a : { o: number; b: number; c: { a: number; c: string; }[]; }
>{o: 1, b: 2, c: [{a: 1, c: '213'}]} : { o: number; b: number; c: { a: number; c: string; }[]; }
>o : number
>1 : 1
>b : number
>2 : 2
>c : { a: number; c: string; }[]
>[{a: 1, c: '213'}] : { a: number; c: string; }[]
>{a: 1, c: '213'} : { a: number; c: string; }
>a : number
>1 : 1
>c : string
>'213' : "213"
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
>assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) : void
>assign : <T>(o: T, a: RecursivePartial<T>) => void
>a : { o: number; b: number; c: { a: number; c: string; }[]; }
>{o: 2, c: {0: {a: 2, c: '213123'}}} : { o: number; c: { 0: { a: number; c: string; }; }; }
>o : number
>2 : 2
>c : { 0: { a: number; c: string; }; }
>{0: {a: 2, c: '213123'}} : { 0: { a: number; c: string; }; }
>0 : { a: number; c: string; }
>{a: 2, c: '213123'} : { a: number; c: string; }
>a : number
>2 : 2
>c : string
>'213123' : "213123"

View File

@@ -341,3 +341,15 @@ declare interface ExtractFooBar<FB extends FooBar> { }
type Extracted<Struct> = {
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
}
// Repro from #22985
type RecursivePartial<T> = {
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
T[P] extends object ? RecursivePartial<T[P]> : T[P];
};
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})