From 1b4bce236eeb2dc6ed0f3a5467b15f5bedeb2dfa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 14:37:31 -0800 Subject: [PATCH 01/13] Infer contextual types from return types through generic functions --- src/compiler/checker.ts | 46 +++++++++++++++++++++++++++-------------- src/compiler/types.ts | 1 + 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cb132ebf927e8..352a5c31592d6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14591,18 +14591,18 @@ namespace ts { } function inferFromProperties(source: Type, target: Type) { - if (isTupleType(source)) { + if (isArrayType(source) || isTupleType(source)) { if (isTupleType(target)) { - const sourceLength = getLengthOfTupleType(source); + const sourceLength = isTupleType(source) ? getLengthOfTupleType(source) : 0; const targetLength = getLengthOfTupleType(target); - const sourceRestType = getRestTypeOfTupleType(source); + const sourceRestType = isTupleType(source) ? getRestTypeOfTupleType(source) : getElementTypeOfArrayType(source); const targetRestType = getRestTypeOfTupleType(target); const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength; for (let i = 0; i < fixedLength; i++) { - inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]); + inferFromTypes(i < sourceLength ? (source).typeArguments![i] : sourceRestType!, target.typeArguments![i]); } if (targetRestType) { - const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : []; + const types = fixedLength < sourceLength ? (source).typeArguments!.slice(fixedLength, sourceLength) : []; if (sourceRestType) { types.push(sourceRestType); } @@ -17694,14 +17694,28 @@ namespace ts { // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node: Expression): Type | undefined { - let contextualType = getContextualType(node); - contextualType = contextualType && mapType(contextualType, getApparentType); - if (contextualType && contextualType.flags & TypeFlags.Union) { - if (isObjectLiteralExpression(node)) { - return discriminateContextualTypeByObjectMembers(node, contextualType as UnionType); + const contextualType = instantiateContextualType(getContextualType(node), node); + if (contextualType) { + const apparentType = mapType(contextualType, getApparentType); + if (apparentType.flags & TypeFlags.Union) { + if (isObjectLiteralExpression(node)) { + return discriminateContextualTypeByObjectMembers(node, apparentType as UnionType); + } + else if (isJsxAttributes(node)) { + return discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType); + } } - else if (isJsxAttributes(node)) { - return discriminateContextualTypeByJSXAttributes(node, contextualType as UnionType); + return apparentType; + } + } + + // If the given contextual type constains instantiable types and if a mapper representing + // return type inferences is available, instantiate those types using that mapper. + function instantiateContextualType(contextualType: Type | undefined, node: Expression): Type | undefined { + if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { + const returnMapper = (getContextualMapper(node)).returnMapper; + if (returnMapper) { + return mapType(contextualType, t => t.flags & TypeFlags.Instantiable ? instantiateType(t, returnMapper) : t); } } return contextualType; @@ -19847,6 +19861,9 @@ namespace ts { const inferenceTargetType = getReturnTypeOfSignature(signature); // Inferences made from return types have lower priority than all other inferences. inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType); + // Create a type mapper for instantiating generic contextual types using the inferences made + // from the return type. + context.returnMapper = cloneTypeMapper(context); } } @@ -23022,12 +23039,9 @@ namespace ts { } function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type, forceTuple?: boolean): Type { - if (arguments.length === 2) { - contextualType = getContextualType(node); - } const type = checkExpression(node, checkMode, forceTuple); return isTypeAssertion(node) ? type : - getWidenedLiteralLikeTypeForContextualType(type, contextualType); + getWidenedLiteralLikeTypeForContextualType(type, instantiateContextualType(arguments.length === 2 ? getContextualType(node) : contextualType, node)); } function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c6c34c7434e0a..a2e1fe7379832 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4364,6 +4364,7 @@ namespace ts { inferences: InferenceInfo[]; // Inferences made for each type parameter flags: InferenceFlags; // Inference flags compareTypes: TypeComparer; // Type comparer function + returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any) } /* @internal */ From da9feca0b00ad2fb59ca23a0cbe882066521f4bb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 14:38:04 -0800 Subject: [PATCH 02/13] Accept new baselines --- .../reference/errorMessagesIntersectionTypes02.errors.txt | 8 ++++---- .../reference/errorMessagesIntersectionTypes02.types | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt index 6a9dd26706c2f..1225d3662cb59 100644 --- a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt +++ b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. +tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: "frizzlebizzle"; } & Bar' is not assignable to type 'FooBar'. Types of property 'fooProp' are incompatible. - Type 'string' is not assignable to type '"hello" | "world"'. + Type '"frizzlebizzle"' is not assignable to type '"hello" | "world"'. ==== tests/cases/compiler/errorMessagesIntersectionTypes02.ts (1 errors) ==== @@ -19,8 +19,8 @@ tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Ty let fooBar: FooBar = mixBar({ ~~~~~~ -!!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. +!!! error TS2322: Type '{ fooProp: "frizzlebizzle"; } & Bar' is not assignable to type 'FooBar'. !!! error TS2322: Types of property 'fooProp' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type '"hello" | "world"'. +!!! error TS2322: Type '"frizzlebizzle"' is not assignable to type '"hello" | "world"'. fooProp: "frizzlebizzle" }); \ No newline at end of file diff --git a/tests/baselines/reference/errorMessagesIntersectionTypes02.types b/tests/baselines/reference/errorMessagesIntersectionTypes02.types index ee21ee3ed91f2..f1aa28ca32edb 100644 --- a/tests/baselines/reference/errorMessagesIntersectionTypes02.types +++ b/tests/baselines/reference/errorMessagesIntersectionTypes02.types @@ -18,12 +18,12 @@ declare function mixBar(obj: T): T & Bar; let fooBar: FooBar = mixBar({ >fooBar : FooBar ->mixBar({ fooProp: "frizzlebizzle"}) : { fooProp: string; } & Bar +>mixBar({ fooProp: "frizzlebizzle"}) : { fooProp: "frizzlebizzle"; } & Bar >mixBar : (obj: T) => T & Bar ->{ fooProp: "frizzlebizzle"} : { fooProp: string; } +>{ fooProp: "frizzlebizzle"} : { fooProp: "frizzlebizzle"; } fooProp: "frizzlebizzle" ->fooProp : string +>fooProp : "frizzlebizzle" >"frizzlebizzle" : "frizzlebizzle" }); From bb1c91fac6945481e0a56cebce98b855482377e4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 17:04:29 -0800 Subject: [PATCH 03/13] Remove literal freshness when contextual type is a literal type --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 352a5c31592d6..f66667d2ddce4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22962,7 +22962,9 @@ namespace ts { context.contextualMapper = contextualMapper; const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive : contextualMapper ? CheckMode.Inferential : CheckMode.Contextual; - const result = checkExpression(node, checkMode); + const type = checkExpression(node, checkMode); + const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node)) ? + getRegularTypeOfLiteralType(type) : type; context.contextualType = saveContextualType; context.contextualMapper = saveContextualMapper; return result; From 4163d2dee4d78e26e831f9c369515fd1028d7cde Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 17:16:52 -0800 Subject: [PATCH 04/13] Add tests --- .../inferFromGenericFunctionReturnTypes3.ts | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts diff --git a/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts new file mode 100644 index 0000000000000..e44e7c4a5e020 --- /dev/null +++ b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts @@ -0,0 +1,174 @@ +// @strict: true +// @target: es6 +// @declaration: true + +// Repros from #5487 + +function truePromise(): Promise { + return Promise.resolve(true); +} + +interface Wrap { + value: T; +} + +function wrap(value: T): Wrap { + return { value }; +} + +function wrappedFoo(): Wrap<'foo'> { + return wrap('foo'); +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { + return { value }; +} + +function wrappedBar(): Wrap<'bar'> { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2: string = 'bar'; + const literal2 = wrapBar(value2); // Error + return wrap(value); +} + +function wrappedBaz(): Wrap<'baz'> { + const value: 'baz' = 'baz'; + return wrap(value); +} + +// Repro from #11152 + +interface FolderContentItem { + type: 'folder' | 'file'; +} + +let a: FolderContentItem[] = []; +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { + return [x, y]; +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { + export const Error = 1; + export const Warning = 2; + export const Information = 3; + export const Hint = 4; +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; + +export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; +} + +function bug(): Diagnostic[] { + let values: any[] = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +}; + +// Repro from #24352 + +interface Person { + phoneNumbers: { + __typename: 'PhoneNumber'; + }[]; +} + +function createPerson(): Person { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +declare function box(value: T): Box; + +type WinCondition = + | { type: 'win', player: string } + | { type: 'draw' }; + +let zz: Box = box({ type: 'draw' }); + +type WinType = 'win' | 'draw'; + +let yy: Box = box('draw'); + +// Repro from #27074 + +interface OK { + kind: "OK"; + value: T; +} +export function ok(value: T): OK { + return { + kind: "OK", + value: value + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); + +// Repro from #25889 + +interface I { + code: 'mapped', + name: string, +} + +const a3: I[] = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { + name: string; + age: number; + position: "STRIKER" | "GOALKEEPER", +}; + +type F = () => Promise>; + +const f1: F = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); +}; From c809002bd3d07df7b6b60893a940c3079c4338fc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 17:17:03 -0800 Subject: [PATCH 05/13] Accept new baselines --- ...FromGenericFunctionReturnTypes3.errors.txt | 177 +++++++ .../inferFromGenericFunctionReturnTypes3.js | 285 +++++++++++ ...ferFromGenericFunctionReturnTypes3.symbols | 409 ++++++++++++++++ ...inferFromGenericFunctionReturnTypes3.types | 452 ++++++++++++++++++ 4 files changed, 1323 insertions(+) create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt new file mode 100644 index 0000000000000..9a0d64c1a5699 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt @@ -0,0 +1,177 @@ +tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(28,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"bar"'. + + +==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (1 errors) ==== + // Repros from #5487 + + function truePromise(): Promise { + return Promise.resolve(true); + } + + interface Wrap { + value: T; + } + + function wrap(value: T): Wrap { + return { value }; + } + + function wrappedFoo(): Wrap<'foo'> { + return wrap('foo'); + } + + function wrapBar(value: 'bar'): Wrap<'bar'> { + return { value }; + } + + function wrappedBar(): Wrap<'bar'> { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2: string = 'bar'; + const literal2 = wrapBar(value2); // Error + ~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"bar"'. + return wrap(value); + } + + function wrappedBaz(): Wrap<'baz'> { + const value: 'baz' = 'baz'; + return wrap(value); + } + + // Repro from #11152 + + interface FolderContentItem { + type: 'folder' | 'file'; + } + + let a: FolderContentItem[] = []; + a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); + + // Repro from #11312 + + let arr: Array<[number, number]> = [[1, 2]] + + let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { + return [x, y]; + }) + + // Repro from #13594 + + export namespace DiagnosticSeverity { + export const Error = 1; + export const Warning = 2; + export const Information = 3; + export const Hint = 4; + } + + export type DiagnosticSeverity = 1 | 2 | 3 | 4; + + export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; + } + + function bug(): Diagnostic[] { + let values: any[] = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + } + }); + } + + // Repro from #22870 + + function objectToMap(obj: any) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); + }; + + // Repro from #24352 + + interface Person { + phoneNumbers: { + __typename: 'PhoneNumber'; + }[]; + } + + function createPerson(): Person { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; + } + + // Repro from #26621 + + type Box = { value: T }; + declare function box(value: T): Box; + + type WinCondition = + | { type: 'win', player: string } + | { type: 'draw' }; + + let zz: Box = box({ type: 'draw' }); + + type WinType = 'win' | 'draw'; + + let yy: Box = box('draw'); + + // Repro from #27074 + + interface OK { + kind: "OK"; + value: T; + } + export function ok(value: T): OK { + return { + kind: "OK", + value: value + }; + } + + let result: OK<[string, number]> = ok(["hello", 12]); + + // Repro from #25889 + + interface I { + code: 'mapped', + name: string, + } + + const a3: I[] = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + } + }); + + // Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + + type Player = { + name: string; + age: number; + position: "STRIKER" | "GOALKEEPER", + }; + + type F = () => Promise>; + + const f1: F = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); + }; + \ No newline at end of file diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js new file mode 100644 index 0000000000000..ca1533bbab121 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js @@ -0,0 +1,285 @@ +//// [inferFromGenericFunctionReturnTypes3.ts] +// Repros from #5487 + +function truePromise(): Promise { + return Promise.resolve(true); +} + +interface Wrap { + value: T; +} + +function wrap(value: T): Wrap { + return { value }; +} + +function wrappedFoo(): Wrap<'foo'> { + return wrap('foo'); +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { + return { value }; +} + +function wrappedBar(): Wrap<'bar'> { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2: string = 'bar'; + const literal2 = wrapBar(value2); // Error + return wrap(value); +} + +function wrappedBaz(): Wrap<'baz'> { + const value: 'baz' = 'baz'; + return wrap(value); +} + +// Repro from #11152 + +interface FolderContentItem { + type: 'folder' | 'file'; +} + +let a: FolderContentItem[] = []; +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { + return [x, y]; +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { + export const Error = 1; + export const Warning = 2; + export const Information = 3; + export const Hint = 4; +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; + +export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; +} + +function bug(): Diagnostic[] { + let values: any[] = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +}; + +// Repro from #24352 + +interface Person { + phoneNumbers: { + __typename: 'PhoneNumber'; + }[]; +} + +function createPerson(): Person { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +declare function box(value: T): Box; + +type WinCondition = + | { type: 'win', player: string } + | { type: 'draw' }; + +let zz: Box = box({ type: 'draw' }); + +type WinType = 'win' | 'draw'; + +let yy: Box = box('draw'); + +// Repro from #27074 + +interface OK { + kind: "OK"; + value: T; +} +export function ok(value: T): OK { + return { + kind: "OK", + value: value + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); + +// Repro from #25889 + +interface I { + code: 'mapped', + name: string, +} + +const a3: I[] = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { + name: string; + age: number; + position: "STRIKER" | "GOALKEEPER", +}; + +type F = () => Promise>; + +const f1: F = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); +}; + + +//// [inferFromGenericFunctionReturnTypes3.js] +// Repros from #5487 +function truePromise() { + return Promise.resolve(true); +} +function wrap(value) { + return { value }; +} +function wrappedFoo() { + return wrap('foo'); +} +function wrapBar(value) { + return { value }; +} +function wrappedBar() { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2 = 'bar'; + const literal2 = wrapBar(value2); // Error + return wrap(value); +} +function wrappedBaz() { + const value = 'baz'; + return wrap(value); +} +let a = []; +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); +// Repro from #11312 +let arr = [[1, 2]]; +let mappedArr = arr.map(([x, y]) => { + return [x, y]; +}); +// Repro from #13594 +export var DiagnosticSeverity; +(function (DiagnosticSeverity) { + DiagnosticSeverity.Error = 1; + DiagnosticSeverity.Warning = 2; + DiagnosticSeverity.Information = 3; + DiagnosticSeverity.Hint = 4; +})(DiagnosticSeverity || (DiagnosticSeverity = {})); +function bug() { + let values = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + }; + }); +} +// Repro from #22870 +function objectToMap(obj) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +} +; +function createPerson() { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; +} +let zz = box({ type: 'draw' }); +let yy = box('draw'); +export function ok(value) { + return { + kind: "OK", + value: value + }; +} +let result = ok(["hello", 12]); +const a3 = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + }; +}); +const f1 = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); +}; + + +//// [inferFromGenericFunctionReturnTypes3.d.ts] +export declare namespace DiagnosticSeverity { + const Error = 1; + const Warning = 2; + const Information = 3; + const Hint = 4; +} +export declare type DiagnosticSeverity = 1 | 2 | 3 | 4; +export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; +} +interface OK { + kind: "OK"; + value: T; +} +export declare function ok(value: T): OK; +export {}; diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols new file mode 100644 index 0000000000000..16beb0546de2b --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols @@ -0,0 +1,409 @@ +=== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts === +// Repros from #5487 + +function truePromise(): Promise { +>truePromise : Symbol(truePromise, Decl(inferFromGenericFunctionReturnTypes3.ts, 0, 0)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + return Promise.resolve(true); +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +} + +interface Wrap { +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 6, 15)) + + value: T; +>value : Symbol(Wrap.value, Decl(inferFromGenericFunctionReturnTypes3.ts, 6, 19)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 6, 15)) +} + +function wrap(value: T): Wrap { +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 14)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 17)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 14)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 14)) + + return { value }; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 11, 12)) +} + +function wrappedFoo(): Wrap<'foo'> { +>wrappedFoo : Symbol(wrappedFoo, Decl(inferFromGenericFunctionReturnTypes3.ts, 12, 1)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + return wrap('foo'); +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 18, 17)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + return { value }; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 19, 12)) +} + +function wrappedBar(): Wrap<'bar'> { +>wrappedBar : Symbol(wrappedBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 20, 1)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + const value = 'bar'; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 23, 9)) + + const inferred = wrapBar(value); +>inferred : Symbol(inferred, Decl(inferFromGenericFunctionReturnTypes3.ts, 24, 9)) +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 23, 9)) + + const literal = wrapBar('bar'); +>literal : Symbol(literal, Decl(inferFromGenericFunctionReturnTypes3.ts, 25, 9)) +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) + + const value2: string = 'bar'; +>value2 : Symbol(value2, Decl(inferFromGenericFunctionReturnTypes3.ts, 26, 9)) + + const literal2 = wrapBar(value2); // Error +>literal2 : Symbol(literal2, Decl(inferFromGenericFunctionReturnTypes3.ts, 27, 9)) +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) +>value2 : Symbol(value2, Decl(inferFromGenericFunctionReturnTypes3.ts, 26, 9)) + + return wrap(value); +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 23, 9)) +} + +function wrappedBaz(): Wrap<'baz'> { +>wrappedBaz : Symbol(wrappedBaz, Decl(inferFromGenericFunctionReturnTypes3.ts, 29, 1)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + const value: 'baz' = 'baz'; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 32, 9)) + + return wrap(value); +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 32, 9)) +} + +// Repro from #11152 + +interface FolderContentItem { +>FolderContentItem : Symbol(FolderContentItem, Decl(inferFromGenericFunctionReturnTypes3.ts, 34, 1)) + + type: 'folder' | 'file'; +>type : Symbol(FolderContentItem.type, Decl(inferFromGenericFunctionReturnTypes3.ts, 38, 29)) +} + +let a: FolderContentItem[] = []; +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes3.ts, 42, 3)) +>FolderContentItem : Symbol(FolderContentItem, Decl(inferFromGenericFunctionReturnTypes3.ts, 34, 1)) + +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes3.ts, 42, 3)) +>[1, 2, 3, 4, 5].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>v : Symbol(v, Decl(inferFromGenericFunctionReturnTypes3.ts, 43, 24)) +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 43, 31)) + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] +>arr : Symbol(arr, Decl(inferFromGenericFunctionReturnTypes3.ts, 47, 3)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { +>mappedArr : Symbol(mappedArr, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 3)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>arr.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(inferFromGenericFunctionReturnTypes3.ts, 47, 3)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 51)) +>y : Symbol(y, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 53)) + + return [x, y]; +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 51)) +>y : Symbol(y, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 53)) + +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) + + export const Error = 1; +>Error : Symbol(Error, Decl(inferFromGenericFunctionReturnTypes3.ts, 56, 13)) + + export const Warning = 2; +>Warning : Symbol(Warning, Decl(inferFromGenericFunctionReturnTypes3.ts, 57, 13)) + + export const Information = 3; +>Information : Symbol(Information, Decl(inferFromGenericFunctionReturnTypes3.ts, 58, 13)) + + export const Hint = 4; +>Hint : Symbol(Hint, Decl(inferFromGenericFunctionReturnTypes3.ts, 59, 13)) +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) + +export interface Diagnostic { +>Diagnostic : Symbol(Diagnostic, Decl(inferFromGenericFunctionReturnTypes3.ts, 62, 47)) + + severity?: DiagnosticSeverity; +>severity : Symbol(Diagnostic.severity, Decl(inferFromGenericFunctionReturnTypes3.ts, 64, 29)) +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) + + code?: number | string; +>code : Symbol(Diagnostic.code, Decl(inferFromGenericFunctionReturnTypes3.ts, 65, 31)) + + source?: string; +>source : Symbol(Diagnostic.source, Decl(inferFromGenericFunctionReturnTypes3.ts, 66, 24)) + + message: string; +>message : Symbol(Diagnostic.message, Decl(inferFromGenericFunctionReturnTypes3.ts, 67, 17)) +} + +function bug(): Diagnostic[] { +>bug : Symbol(bug, Decl(inferFromGenericFunctionReturnTypes3.ts, 69, 1)) +>Diagnostic : Symbol(Diagnostic, Decl(inferFromGenericFunctionReturnTypes3.ts, 62, 47)) + + let values: any[] = []; +>values : Symbol(values, Decl(inferFromGenericFunctionReturnTypes3.ts, 72, 4)) + + return values.map((value) => { +>values.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>values : Symbol(values, Decl(inferFromGenericFunctionReturnTypes3.ts, 72, 4)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 73, 20)) + + return { + severity: DiagnosticSeverity.Error, +>severity : Symbol(severity, Decl(inferFromGenericFunctionReturnTypes3.ts, 74, 10)) +>DiagnosticSeverity.Error : Symbol(DiagnosticSeverity.Error, Decl(inferFromGenericFunctionReturnTypes3.ts, 56, 13)) +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) +>Error : Symbol(DiagnosticSeverity.Error, Decl(inferFromGenericFunctionReturnTypes3.ts, 56, 13)) + + message: 'message' +>message : Symbol(message, Decl(inferFromGenericFunctionReturnTypes3.ts, 75, 38)) + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { +>objectToMap : Symbol(objectToMap, Decl(inferFromGenericFunctionReturnTypes3.ts, 79, 1)) +>obj : Symbol(obj, Decl(inferFromGenericFunctionReturnTypes3.ts, 83, 21)) + + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Object.keys(obj).map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>Object.keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inferFromGenericFunctionReturnTypes3.ts, 83, 21)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>key : Symbol(key, Decl(inferFromGenericFunctionReturnTypes3.ts, 84, 37)) +>key : Symbol(key, Decl(inferFromGenericFunctionReturnTypes3.ts, 84, 37)) +>obj : Symbol(obj, Decl(inferFromGenericFunctionReturnTypes3.ts, 83, 21)) +>key : Symbol(key, Decl(inferFromGenericFunctionReturnTypes3.ts, 84, 37)) + +}; + +// Repro from #24352 + +interface Person { +>Person : Symbol(Person, Decl(inferFromGenericFunctionReturnTypes3.ts, 85, 2)) + + phoneNumbers: { +>phoneNumbers : Symbol(Person.phoneNumbers, Decl(inferFromGenericFunctionReturnTypes3.ts, 89, 18)) + + __typename: 'PhoneNumber'; +>__typename : Symbol(__typename, Decl(inferFromGenericFunctionReturnTypes3.ts, 90, 17)) + + }[]; +} + +function createPerson(): Person { +>createPerson : Symbol(createPerson, Decl(inferFromGenericFunctionReturnTypes3.ts, 93, 1)) +>Person : Symbol(Person, Decl(inferFromGenericFunctionReturnTypes3.ts, 85, 2)) + + return { + phoneNumbers: [1].map(() => ({ +>phoneNumbers : Symbol(phoneNumbers, Decl(inferFromGenericFunctionReturnTypes3.ts, 96, 10)) +>[1].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) + + __typename: 'PhoneNumber' +>__typename : Symbol(__typename, Decl(inferFromGenericFunctionReturnTypes3.ts, 97, 34)) + + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 9)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 15)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 9)) + +declare function box(value: T): Box; +>box : Symbol(box, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 27)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 21)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 24)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 21)) +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 21)) + +type WinCondition = +>WinCondition : Symbol(WinCondition, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 42)) + + | { type: 'win', player: string } +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 109, 7)) +>player : Symbol(player, Decl(inferFromGenericFunctionReturnTypes3.ts, 109, 20)) + + | { type: 'draw' }; +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 110, 7)) + +let zz: Box = box({ type: 'draw' }); +>zz : Symbol(zz, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 3)) +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>WinCondition : Symbol(WinCondition, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 42)) +>box : Symbol(box, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 27)) +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 33)) + +type WinType = 'win' | 'draw'; +>WinType : Symbol(WinType, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 50)) + +let yy: Box = box('draw'); +>yy : Symbol(yy, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 3)) +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>WinType : Symbol(WinType, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 50)) +>box : Symbol(box, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 27)) + +// Repro from #27074 + +interface OK { +>OK : Symbol(OK, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 35)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 120, 13)) + + kind: "OK"; +>kind : Symbol(OK.kind, Decl(inferFromGenericFunctionReturnTypes3.ts, 120, 17)) + + value: T; +>value : Symbol(OK.value, Decl(inferFromGenericFunctionReturnTypes3.ts, 121, 15)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 120, 13)) +} +export function ok(value: T): OK { +>ok : Symbol(ok, Decl(inferFromGenericFunctionReturnTypes3.ts, 123, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 19)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 22)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 19)) +>OK : Symbol(OK, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 35)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 19)) + + return { + kind: "OK", +>kind : Symbol(kind, Decl(inferFromGenericFunctionReturnTypes3.ts, 125, 12)) + + value: value +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 126, 19)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 22)) + + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); +>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes3.ts, 131, 3)) +>OK : Symbol(OK, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 35)) +>ok : Symbol(ok, Decl(inferFromGenericFunctionReturnTypes3.ts, 123, 1)) + +// Repro from #25889 + +interface I { +>I : Symbol(I, Decl(inferFromGenericFunctionReturnTypes3.ts, 131, 53)) + + code: 'mapped', +>code : Symbol(I.code, Decl(inferFromGenericFunctionReturnTypes3.ts, 135, 13)) + + name: string, +>name : Symbol(I.name, Decl(inferFromGenericFunctionReturnTypes3.ts, 136, 19)) +} + +const a3: I[] = ['a', 'b'].map(name => { +>a3 : Symbol(a3, Decl(inferFromGenericFunctionReturnTypes3.ts, 140, 5)) +>I : Symbol(I, Decl(inferFromGenericFunctionReturnTypes3.ts, 131, 53)) +>['a', 'b'].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 140, 31)) + + return { + code: 'mapped', +>code : Symbol(code, Decl(inferFromGenericFunctionReturnTypes3.ts, 141, 12)) + + name, +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 142, 23)) + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { +>Player : Symbol(Player, Decl(inferFromGenericFunctionReturnTypes3.ts, 145, 3)) + + name: string; +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 149, 15)) + + age: number; +>age : Symbol(age, Decl(inferFromGenericFunctionReturnTypes3.ts, 150, 17)) + + position: "STRIKER" | "GOALKEEPER", +>position : Symbol(position, Decl(inferFromGenericFunctionReturnTypes3.ts, 151, 16)) + +}; + +type F = () => Promise>; +>F : Symbol(F, Decl(inferFromGenericFunctionReturnTypes3.ts, 153, 2)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Player : Symbol(Player, Decl(inferFromGenericFunctionReturnTypes3.ts, 145, 3)) + +const f1: F = () => { +>f1 : Symbol(f1, Decl(inferFromGenericFunctionReturnTypes3.ts, 157, 5)) +>F : Symbol(F, Decl(inferFromGenericFunctionReturnTypes3.ts, 153, 2)) + + return Promise.all([ +>Promise.all : Symbol(PromiseConstructor.all, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --) ... and 6 more) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>all : Symbol(PromiseConstructor.all, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --) ... and 6 more) + { + name: "David Gomes", +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 159, 9)) + + age: 23, +>age : Symbol(age, Decl(inferFromGenericFunctionReturnTypes3.ts, 160, 32)) + + position: "GOALKEEPER", +>position : Symbol(position, Decl(inferFromGenericFunctionReturnTypes3.ts, 161, 20)) + + }, { + name: "Cristiano Ronaldo", +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 163, 12)) + + age: 33, +>age : Symbol(age, Decl(inferFromGenericFunctionReturnTypes3.ts, 164, 38)) + + position: "STRIKER", +>position : Symbol(position, Decl(inferFromGenericFunctionReturnTypes3.ts, 165, 20)) + } + ]); +}; + diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types new file mode 100644 index 0000000000000..e983cc6481924 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types @@ -0,0 +1,452 @@ +=== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts === +// Repros from #5487 + +function truePromise(): Promise { +>truePromise : () => Promise +>true : true + + return Promise.resolve(true); +>Promise.resolve(true) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>true : true +} + +interface Wrap { + value: T; +>value : T +} + +function wrap(value: T): Wrap { +>wrap : (value: T) => Wrap +>value : T + + return { value }; +>{ value } : { value: T; } +>value : T +} + +function wrappedFoo(): Wrap<'foo'> { +>wrappedFoo : () => Wrap<"foo"> + + return wrap('foo'); +>wrap('foo') : Wrap<"foo"> +>wrap : (value: T) => Wrap +>'foo' : "foo" +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { +>wrapBar : (value: "bar") => Wrap<"bar"> +>value : "bar" + + return { value }; +>{ value } : { value: "bar"; } +>value : "bar" +} + +function wrappedBar(): Wrap<'bar'> { +>wrappedBar : () => Wrap<"bar"> + + const value = 'bar'; +>value : "bar" +>'bar' : "bar" + + const inferred = wrapBar(value); +>inferred : Wrap<"bar"> +>wrapBar(value) : Wrap<"bar"> +>wrapBar : (value: "bar") => Wrap<"bar"> +>value : "bar" + + const literal = wrapBar('bar'); +>literal : Wrap<"bar"> +>wrapBar('bar') : Wrap<"bar"> +>wrapBar : (value: "bar") => Wrap<"bar"> +>'bar' : "bar" + + const value2: string = 'bar'; +>value2 : string +>'bar' : "bar" + + const literal2 = wrapBar(value2); // Error +>literal2 : Wrap<"bar"> +>wrapBar(value2) : Wrap<"bar"> +>wrapBar : (value: "bar") => Wrap<"bar"> +>value2 : string + + return wrap(value); +>wrap(value) : Wrap<"bar"> +>wrap : (value: T) => Wrap +>value : "bar" +} + +function wrappedBaz(): Wrap<'baz'> { +>wrappedBaz : () => Wrap<"baz"> + + const value: 'baz' = 'baz'; +>value : "baz" +>'baz' : "baz" + + return wrap(value); +>wrap(value) : Wrap<"baz"> +>wrap : (value: T) => Wrap +>value : "baz" +} + +// Repro from #11152 + +interface FolderContentItem { + type: 'folder' | 'file'; +>type : "folder" | "file" +} + +let a: FolderContentItem[] = []; +>a : FolderContentItem[] +>[] : never[] + +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); +>a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })) : { type: "folder"; }[] +>a : FolderContentItem[] +>[1, 2, 3, 4, 5].map(v => ({ type: 'folder' })) : { type: "folder"; }[] +>[1, 2, 3, 4, 5].map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>[1, 2, 3, 4, 5] : number[] +>1 : 1 +>2 : 2 +>3 : 3 +>4 : 4 +>5 : 5 +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>v => ({ type: 'folder' }) : (v: number) => { type: "folder"; } +>v : number +>({ type: 'folder' }) : { type: "folder"; } +>{ type: 'folder' } : { type: "folder"; } +>type : "folder" +>'folder' : "folder" + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] +>arr : [number, number][] +>[[1, 2]] : [number, number][] +>[1, 2] : [number, number] +>1 : 1 +>2 : 2 + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { +>mappedArr : [number, number][] +>arr.map(([x, y]) => { return [x, y];}) : [number, number][] +>arr.map : (callbackfn: (value: [number, number], index: number, array: [number, number][]) => U, thisArg?: any) => U[] +>arr : [number, number][] +>map : (callbackfn: (value: [number, number], index: number, array: [number, number][]) => U, thisArg?: any) => U[] +>([x, y]) => { return [x, y];} : ([x, y]: [number, number]) => [number, number] +>x : number +>y : number + + return [x, y]; +>[x, y] : [number, number] +>x : number +>y : number + +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { +>DiagnosticSeverity : typeof DiagnosticSeverity + + export const Error = 1; +>Error : 1 +>1 : 1 + + export const Warning = 2; +>Warning : 2 +>2 : 2 + + export const Information = 3; +>Information : 3 +>3 : 3 + + export const Hint = 4; +>Hint : 4 +>4 : 4 +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; +>DiagnosticSeverity : DiagnosticSeverity + +export interface Diagnostic { + severity?: DiagnosticSeverity; +>severity : 1 | 2 | 3 | 4 | undefined + + code?: number | string; +>code : string | number | undefined + + source?: string; +>source : string | undefined + + message: string; +>message : string +} + +function bug(): Diagnostic[] { +>bug : () => Diagnostic[] + + let values: any[] = []; +>values : any[] +>[] : never[] + + return values.map((value) => { +>values.map((value) => { return { severity: DiagnosticSeverity.Error, message: 'message' } }) : { severity: 1; message: string; }[] +>values.map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] +>values : any[] +>map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] +>(value) => { return { severity: DiagnosticSeverity.Error, message: 'message' } } : (value: any) => { severity: 1; message: string; } +>value : any + + return { +>{ severity: DiagnosticSeverity.Error, message: 'message' } : { severity: 1; message: string; } + + severity: DiagnosticSeverity.Error, +>severity : 1 +>DiagnosticSeverity.Error : 1 +>DiagnosticSeverity : typeof DiagnosticSeverity +>Error : 1 + + message: 'message' +>message : string +>'message' : "message" + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { +>objectToMap : (obj: any) => Map +>obj : any + + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +>new Map(Object.keys(obj).map(key => [key, obj[key]])) : Map +>Map : MapConstructor +>Object.keys(obj).map(key => [key, obj[key]]) : [string, any][] +>Object.keys(obj).map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>Object.keys(obj) : string[] +>Object.keys : (o: {}) => string[] +>Object : ObjectConstructor +>keys : (o: {}) => string[] +>obj : any +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>key => [key, obj[key]] : (key: string) => [string, any] +>key : string +>[key, obj[key]] : [string, any] +>key : string +>obj[key] : any +>obj : any +>key : string + +}; + +// Repro from #24352 + +interface Person { + phoneNumbers: { +>phoneNumbers : { __typename: "PhoneNumber"; }[] + + __typename: 'PhoneNumber'; +>__typename : "PhoneNumber" + + }[]; +} + +function createPerson(): Person { +>createPerson : () => Person + + return { +>{ phoneNumbers: [1].map(() => ({ __typename: 'PhoneNumber' })) } : { phoneNumbers: { __typename: "PhoneNumber"; }[]; } + + phoneNumbers: [1].map(() => ({ +>phoneNumbers : { __typename: "PhoneNumber"; }[] +>[1].map(() => ({ __typename: 'PhoneNumber' })) : { __typename: "PhoneNumber"; }[] +>[1].map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>[1] : number[] +>1 : 1 +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>() => ({ __typename: 'PhoneNumber' }) : () => { __typename: "PhoneNumber"; } +>({ __typename: 'PhoneNumber' }) : { __typename: "PhoneNumber"; } +>{ __typename: 'PhoneNumber' } : { __typename: "PhoneNumber"; } + + __typename: 'PhoneNumber' +>__typename : "PhoneNumber" +>'PhoneNumber' : "PhoneNumber" + + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +>Box : Box +>value : T + +declare function box(value: T): Box; +>box : (value: T) => Box +>value : T + +type WinCondition = +>WinCondition : WinCondition + + | { type: 'win', player: string } +>type : "win" +>player : string + + | { type: 'draw' }; +>type : "draw" + +let zz: Box = box({ type: 'draw' }); +>zz : Box +>box({ type: 'draw' }) : Box<{ type: "draw"; }> +>box : (value: T) => Box +>{ type: 'draw' } : { type: "draw"; } +>type : "draw" +>'draw' : "draw" + +type WinType = 'win' | 'draw'; +>WinType : "win" | "draw" + +let yy: Box = box('draw'); +>yy : Box<"win" | "draw"> +>box('draw') : Box<"draw"> +>box : (value: T) => Box +>'draw' : "draw" + +// Repro from #27074 + +interface OK { + kind: "OK"; +>kind : "OK" + + value: T; +>value : T +} +export function ok(value: T): OK { +>ok : (value: T) => OK +>value : T + + return { +>{ kind: "OK", value: value } : { kind: "OK"; value: T; } + + kind: "OK", +>kind : "OK" +>"OK" : "OK" + + value: value +>value : T +>value : T + + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); +>result : OK<[string, number]> +>ok(["hello", 12]) : OK<[string, number]> +>ok : (value: T) => OK +>["hello", 12] : [string, number] +>"hello" : "hello" +>12 : 12 + +// Repro from #25889 + +interface I { + code: 'mapped', +>code : "mapped" + + name: string, +>name : string +} + +const a3: I[] = ['a', 'b'].map(name => { +>a3 : I[] +>['a', 'b'].map(name => { return { code: 'mapped', name, }}) : { code: "mapped"; name: string; }[] +>['a', 'b'].map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>['a', 'b'] : string[] +>'a' : "a" +>'b' : "b" +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>name => { return { code: 'mapped', name, }} : (name: string) => { code: "mapped"; name: string; } +>name : string + + return { +>{ code: 'mapped', name, } : { code: "mapped"; name: string; } + + code: 'mapped', +>code : "mapped" +>'mapped' : "mapped" + + name, +>name : string + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { +>Player : Player + + name: string; +>name : string + + age: number; +>age : number + + position: "STRIKER" | "GOALKEEPER", +>position : "STRIKER" | "GOALKEEPER" + +}; + +type F = () => Promise>; +>F : F + +const f1: F = () => { +>f1 : F +>() => { return Promise.all([ { name: "David Gomes", age: 23, position: "GOALKEEPER", }, { name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } ]);} : () => Promise<[{ name: string; age: number; position: "GOALKEEPER"; }, { name: string; age: number; position: "STRIKER"; }]> + + return Promise.all([ +>Promise.all([ { name: "David Gomes", age: 23, position: "GOALKEEPER", }, { name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } ]) : Promise<[{ name: string; age: number; position: "GOALKEEPER"; }, { name: string; age: number; position: "STRIKER"; }]> +>Promise.all : { (values: Iterable>): Promise; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: (T | PromiseLike)[]): Promise; } +>Promise : PromiseConstructor +>all : { (values: Iterable>): Promise; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: (T | PromiseLike)[]): Promise; } +>[ { name: "David Gomes", age: 23, position: "GOALKEEPER", }, { name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } ] : [{ name: string; age: number; position: "GOALKEEPER"; }, { name: string; age: number; position: "STRIKER"; }] + { +>{ name: "David Gomes", age: 23, position: "GOALKEEPER", } : { name: string; age: number; position: "GOALKEEPER"; } + + name: "David Gomes", +>name : string +>"David Gomes" : "David Gomes" + + age: 23, +>age : number +>23 : 23 + + position: "GOALKEEPER", +>position : "GOALKEEPER" +>"GOALKEEPER" : "GOALKEEPER" + + }, { +>{ name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } : { name: string; age: number; position: "STRIKER"; } + + name: "Cristiano Ronaldo", +>name : string +>"Cristiano Ronaldo" : "Cristiano Ronaldo" + + age: 33, +>age : number +>33 : 33 + + position: "STRIKER", +>position : "STRIKER" +>"STRIKER" : "STRIKER" + } + ]); +}; + From 0b366ce751784e6aaced01daa107b9c9770d2996 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 18 Jan 2019 14:47:58 -0800 Subject: [PATCH 06/13] Address CR feedback --- src/compiler/checker.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f66667d2ddce4..c85b7457f734a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17715,12 +17715,28 @@ namespace ts { if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { const returnMapper = (getContextualMapper(node)).returnMapper; if (returnMapper) { - return mapType(contextualType, t => t.flags & TypeFlags.Instantiable ? instantiateType(t, returnMapper) : t); + return instantiateInstantiableTypes(contextualType, returnMapper); } } return contextualType; } + // This function is similar to instantiateType, except (a) that it only instantiates types that + // are classified as instantiable (i.e. it doesn't instantiate object types), and (b) it performs + // no reductions on instantiated union types. + function instantiateInstantiableTypes(type: Type, mapper: TypeMapper): Type { + if (type.flags & TypeFlags.Instantiable) { + return instantiateType(type, mapper); + } + if (type.flags & TypeFlags.Union) { + getUnionType(map((type).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); + } + if (type.flags & TypeFlags.Intersection) { + getIntersectionType(map((type).types, t => instantiateInstantiableTypes(t, mapper))); + } + return type; + } + /** * Woah! Do you really want to use this function? * @@ -22963,6 +22979,9 @@ namespace ts { const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive : contextualMapper ? CheckMode.Inferential : CheckMode.Contextual; const type = checkExpression(node, checkMode); + // We strip literal freshness when an appropriate contextual type is present such that contextually typed + // literals always preserve their literal types (otherwise they might widen during type inference). An alternative + // here would be to not mark contextually typed literals as fresh in the first place. const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node)) ? getRegularTypeOfLiteralType(type) : type; context.contextualType = saveContextualType; From 0b1da02a62e3bb88611514840e6cc397ef33eab8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 18 Jan 2019 16:02:13 -0800 Subject: [PATCH 07/13] Add missing return statements (ugh) --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c85b7457f734a..7ba3b2771c3f9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17729,10 +17729,10 @@ namespace ts { return instantiateType(type, mapper); } if (type.flags & TypeFlags.Union) { - getUnionType(map((type).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); + return getUnionType(map((type).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); } if (type.flags & TypeFlags.Intersection) { - getIntersectionType(map((type).types, t => instantiateInstantiableTypes(t, mapper))); + return getIntersectionType(map((type).types, t => instantiateInstantiableTypes(t, mapper))); } return type; } From 60e7528ee642a03708f9bda31d242d69a6271132 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:20:40 -0800 Subject: [PATCH 08/13] No union type reductions in contextual types --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7ba3b2771c3f9..490453a6b403f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17696,7 +17696,7 @@ namespace ts { function getApparentTypeOfContextualType(node: Expression): Type | undefined { const contextualType = instantiateContextualType(getContextualType(node), node); if (contextualType) { - const apparentType = mapType(contextualType, getApparentType); + const apparentType = mapType(contextualType, getApparentType, /*noReductions*/ true); if (apparentType.flags & TypeFlags.Union) { if (isObjectLiteralExpression(node)) { return discriminateContextualTypeByObjectMembers(node, apparentType as UnionType); @@ -17709,7 +17709,7 @@ namespace ts { } } - // If the given contextual type constains instantiable types and if a mapper representing + // If the given contextual type contains instantiable types and if a mapper representing // return type inferences is available, instantiate those types using that mapper. function instantiateContextualType(contextualType: Type | undefined, node: Expression): Type | undefined { if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { @@ -17721,7 +17721,7 @@ namespace ts { return contextualType; } - // This function is similar to instantiateType, except (a) that it only instantiates types that + // This function is similar to instantiateType, except that (a) it only instantiates types that // are classified as instantiable (i.e. it doesn't instantiate object types), and (b) it performs // no reductions on instantiated union types. function instantiateInstantiableTypes(type: Type, mapper: TypeMapper): Type { From dbea08f9c8be9c2aab63b01cb7c7ca114805aa37 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:21:26 -0800 Subject: [PATCH 09/13] Accept new baselines --- .../reference/objectLiteralExcessProperties.errors.txt | 4 ++-- tests/baselines/reference/objectLiteralExcessProperties.types | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt index 4b034b06206df..e4fc4d69fca99 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt +++ b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt @@ -25,7 +25,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(37,25): error TS2304: Cann tests/cases/compiler/objectLiteralExcessProperties.ts(39,11): error TS2322: Type '{ name: string; }' is not assignable to type 'T'. tests/cases/compiler/objectLiteralExcessProperties.ts(41,11): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T & { prop: boolean; }'. Type '{ name: string; prop: boolean; }' is not assignable to type 'T'. -tests/cases/compiler/objectLiteralExcessProperties.ts(43,43): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T | { prop: boolean; }'. +tests/cases/compiler/objectLiteralExcessProperties.ts(43,43): error TS2322: Type '{ name: string; prop: true; }' is not assignable to type 'T | { prop: boolean; }'. Object literal may only specify known properties, and 'name' does not exist in type '{ prop: boolean; }'. tests/cases/compiler/objectLiteralExcessProperties.ts(45,76): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '{ name: string; } | (T & { prop: boolean; })'. Object literal may only specify known properties, and 'prop' does not exist in type '{ name: string; }'. @@ -119,7 +119,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(49,44): error TS2322: Type // Excess property checks only on non-generic parts of unions const obj3: T | { prop: boolean } = { name: "test", prop: true }; ~~~~~~~~~~~~ -!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T | { prop: boolean; }'. +!!! error TS2322: Type '{ name: string; prop: true; }' is not assignable to type 'T | { prop: boolean; }'. !!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ prop: boolean; }'. // Excess property checks only on non-generic parts of unions const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true }; diff --git a/tests/baselines/reference/objectLiteralExcessProperties.types b/tests/baselines/reference/objectLiteralExcessProperties.types index 8765432ab7040..812f48c89048c 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.types +++ b/tests/baselines/reference/objectLiteralExcessProperties.types @@ -124,10 +124,10 @@ function test() { const obj3: T | { prop: boolean } = { name: "test", prop: true }; >obj3 : T | { prop: boolean; } >prop : boolean ->{ name: "test", prop: true } : { name: string; prop: boolean; } +>{ name: "test", prop: true } : { name: string; prop: true; } >name : string >"test" : "test" ->prop : boolean +>prop : true >true : true // Excess property checks only on non-generic parts of unions From cf479fc384bad6f171927a4334954331d076003c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:21:41 -0800 Subject: [PATCH 10/13] Add regression test for #29168 --- .../compiler/contextualTypeShouldBeLiteral.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/cases/compiler/contextualTypeShouldBeLiteral.ts b/tests/cases/compiler/contextualTypeShouldBeLiteral.ts index 1012c567a71b5..5da49215f5ff8 100644 --- a/tests/cases/compiler/contextualTypeShouldBeLiteral.ts +++ b/tests/cases/compiler/contextualTypeShouldBeLiteral.ts @@ -93,4 +93,30 @@ let xyz: LikeA | LikeB = { } }; -xyz; \ No newline at end of file +xyz; + +// Repro from #29168 + +interface TestObject { + type?: 'object'; + items: { + [k: string]: TestGeneric; + }; +} + +interface TestString { + type: 'string'; +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; + +const test: TestGeneric = { + items: { + hello: { type: 'string' }, + world: { + items: { + nested: { type: 'string' } + } + } + } +}; From 2ea02517091efd421e9085af8154a8cb1e3db741 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:21:49 -0800 Subject: [PATCH 11/13] Accept new baselines --- .../contextualTypeShouldBeLiteral.js | 39 ++++++++++++- .../contextualTypeShouldBeLiteral.symbols | 56 +++++++++++++++++++ .../contextualTypeShouldBeLiteral.types | 56 +++++++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/contextualTypeShouldBeLiteral.js b/tests/baselines/reference/contextualTypeShouldBeLiteral.js index dcb9da993c1cb..727609a5abd7c 100644 --- a/tests/baselines/reference/contextualTypeShouldBeLiteral.js +++ b/tests/baselines/reference/contextualTypeShouldBeLiteral.js @@ -93,7 +93,34 @@ let xyz: LikeA | LikeB = { } }; -xyz; +xyz; + +// Repro from #29168 + +interface TestObject { + type?: 'object'; + items: { + [k: string]: TestGeneric; + }; +} + +interface TestString { + type: 'string'; +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; + +const test: TestGeneric = { + items: { + hello: { type: 'string' }, + world: { + items: { + nested: { type: 'string' } + } + } + } +}; + //// [contextualTypeShouldBeLiteral.js] "use strict"; @@ -134,3 +161,13 @@ var xyz = { } }; xyz; +var test = { + items: { + hello: { type: 'string' }, + world: { + items: { + nested: { type: 'string' } + } + } + } +}; diff --git a/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols b/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols index 314117b509d94..a38443d4b0232 100644 --- a/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols +++ b/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols @@ -227,3 +227,59 @@ let xyz: LikeA | LikeB = { xyz; >xyz : Symbol(xyz, Decl(contextualTypeShouldBeLiteral.ts, 82, 3)) +// Repro from #29168 + +interface TestObject { +>TestObject : Symbol(TestObject, Decl(contextualTypeShouldBeLiteral.ts, 94, 4)) + + type?: 'object'; +>type : Symbol(TestObject.type, Decl(contextualTypeShouldBeLiteral.ts, 98, 22)) + + items: { +>items : Symbol(TestObject.items, Decl(contextualTypeShouldBeLiteral.ts, 99, 18)) + + [k: string]: TestGeneric; +>k : Symbol(k, Decl(contextualTypeShouldBeLiteral.ts, 101, 5)) +>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1)) + + }; +} + +interface TestString { +>TestString : Symbol(TestString, Decl(contextualTypeShouldBeLiteral.ts, 103, 1)) + + type: 'string'; +>type : Symbol(TestString.type, Decl(contextualTypeShouldBeLiteral.ts, 105, 22)) +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; +>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1)) +>TestString : Symbol(TestString, Decl(contextualTypeShouldBeLiteral.ts, 103, 1)) +>TestObject : Symbol(TestObject, Decl(contextualTypeShouldBeLiteral.ts, 94, 4)) +>k : Symbol(k, Decl(contextualTypeShouldBeLiteral.ts, 109, 50)) + +const test: TestGeneric = { +>test : Symbol(test, Decl(contextualTypeShouldBeLiteral.ts, 111, 5)) +>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1)) + + items: { +>items : Symbol(items, Decl(contextualTypeShouldBeLiteral.ts, 111, 27)) + + hello: { type: 'string' }, +>hello : Symbol(hello, Decl(contextualTypeShouldBeLiteral.ts, 112, 10)) +>type : Symbol(type, Decl(contextualTypeShouldBeLiteral.ts, 113, 12)) + + world: { +>world : Symbol(world, Decl(contextualTypeShouldBeLiteral.ts, 113, 30)) + + items: { +>items : Symbol(items, Decl(contextualTypeShouldBeLiteral.ts, 114, 12)) + + nested: { type: 'string' } +>nested : Symbol(nested, Decl(contextualTypeShouldBeLiteral.ts, 115, 14)) +>type : Symbol(type, Decl(contextualTypeShouldBeLiteral.ts, 116, 17)) + } + } + } +}; + diff --git a/tests/baselines/reference/contextualTypeShouldBeLiteral.types b/tests/baselines/reference/contextualTypeShouldBeLiteral.types index a5867f0de42dc..d9795c7e33f7c 100644 --- a/tests/baselines/reference/contextualTypeShouldBeLiteral.types +++ b/tests/baselines/reference/contextualTypeShouldBeLiteral.types @@ -222,3 +222,59 @@ let xyz: LikeA | LikeB = { xyz; >xyz : LikeA +// Repro from #29168 + +interface TestObject { + type?: 'object'; +>type : "object" | undefined + + items: { +>items : { [k: string]: TestGeneric; } + + [k: string]: TestGeneric; +>k : string + + }; +} + +interface TestString { + type: 'string'; +>type : "string" +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; +>TestGeneric : TestGeneric +>k : string + +const test: TestGeneric = { +>test : TestGeneric +>{ items: { hello: { type: 'string' }, world: { items: { nested: { type: 'string' } } } }} : { items: { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; }; } + + items: { +>items : { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; } +>{ hello: { type: 'string' }, world: { items: { nested: { type: 'string' } } } } : { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; } + + hello: { type: 'string' }, +>hello : { type: "string"; } +>{ type: 'string' } : { type: "string"; } +>type : "string" +>'string' : "string" + + world: { +>world : { items: { nested: { type: "string"; }; }; } +>{ items: { nested: { type: 'string' } } } : { items: { nested: { type: "string"; }; }; } + + items: { +>items : { nested: { type: "string"; }; } +>{ nested: { type: 'string' } } : { nested: { type: "string"; }; } + + nested: { type: 'string' } +>nested : { type: "string"; } +>{ type: 'string' } : { type: "string"; } +>type : "string" +>'string' : "string" + } + } + } +}; + From c58157573e863e4a9838cbd7a62874e06e8f7b2b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 1 Feb 2019 10:48:52 -0800 Subject: [PATCH 12/13] Add breaking change repros --- .../compiler/inferFromGenericFunctionReturnTypes3.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts index e44e7c4a5e020..429d98b6a3954 100644 --- a/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts +++ b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts @@ -172,3 +172,13 @@ const f1: F = () => { } ]); }; + +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error + +enum State { A, B } +type Foo = { state: State } +declare function bar(f: () => T[]): T[]; +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error From 42be36d1826eccd6686906e0c74c2de118083ffd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 1 Feb 2019 10:48:58 -0800 Subject: [PATCH 13/13] Accept new baselines --- ...FromGenericFunctionReturnTypes3.errors.txt | 28 +++++++++- .../inferFromGenericFunctionReturnTypes3.js | 17 ++++++ ...ferFromGenericFunctionReturnTypes3.symbols | 52 +++++++++++++++++ ...inferFromGenericFunctionReturnTypes3.types | 56 +++++++++++++++++++ 4 files changed, 152 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt index 9a0d64c1a5699..7c79c63f78ae4 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt @@ -1,7 +1,13 @@ tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(28,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"bar"'. +tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(175,47): error TS2322: Type 'boolean' is not assignable to type 'true'. +tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(180,26): error TS2322: Type '{ state: State.A; }[] | { state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. + Type '{ state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. + Type '{ state: State.B; }' is not assignable to type '{ state: State.A; }'. + Types of property 'state' are incompatible. + Type 'State.B' is not assignable to type 'State.A'. -==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (1 errors) ==== +==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (3 errors) ==== // Repros from #5487 function truePromise(): Promise { @@ -174,4 +180,24 @@ tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(28,30): error TS234 } ]); }; + + // Breaking change repros from #29478 + + declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; + let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error + ~~~~~~~~ +!!! error TS2322: Type 'boolean' is not assignable to type 'true'. +!!! related TS6502 tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts:174:39: The expected type comes from the return type of this signature. + + enum State { A, B } + type Foo = { state: State } + declare function bar(f: () => T[]): T[]; + let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ state: State.A; }[] | { state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. +!!! error TS2322: Type '{ state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. +!!! error TS2322: Type '{ state: State.B; }' is not assignable to type '{ state: State.A; }'. +!!! error TS2322: Types of property 'state' are incompatible. +!!! error TS2322: Type 'State.B' is not assignable to type 'State.A'. +!!! related TS6502 tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts:179:28: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js index ca1533bbab121..99070e6ddcbe3 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js @@ -169,6 +169,16 @@ const f1: F = () => { } ]); }; + +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error + +enum State { A, B } +type Foo = { state: State } +declare function bar(f: () => T[]): T[]; +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error //// [inferFromGenericFunctionReturnTypes3.js] @@ -261,6 +271,13 @@ const f1 = () => { } ]); }; +let res = foldLeft(true, (acc, t) => acc && t); // Error +var State; +(function (State) { + State[State["A"] = 0] = "A"; + State[State["B"] = 1] = "B"; +})(State || (State = {})); +let x = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error //// [inferFromGenericFunctionReturnTypes3.d.ts] diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols index 16beb0546de2b..7281886e627e0 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols @@ -407,3 +407,55 @@ const f1: F = () => { ]); }; +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +>foldLeft : Symbol(foldLeft, Decl(inferFromGenericFunctionReturnTypes3.ts, 169, 2)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>z : Symbol(z, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 29)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 34)) +>acc : Symbol(acc, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 39)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>t : Symbol(t, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 46)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) + +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error +>res : Symbol(res, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 3)) +>foldLeft : Symbol(foldLeft, Decl(inferFromGenericFunctionReturnTypes3.ts, 169, 2)) +>acc : Symbol(acc, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 35)) +>t : Symbol(t, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 39)) +>acc : Symbol(acc, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 35)) +>t : Symbol(t, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 39)) + +enum State { A, B } +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) +>A : Symbol(State.A, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 12)) +>B : Symbol(State.B, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 15)) + +type Foo = { state: State } +>Foo : Symbol(Foo, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 19)) +>state : Symbol(state, Decl(inferFromGenericFunctionReturnTypes3.ts, 177, 12)) +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) + +declare function bar(f: () => T[]): T[]; +>bar : Symbol(bar, Decl(inferFromGenericFunctionReturnTypes3.ts, 177, 27)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 21)) +>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 24)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 21)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 21)) + +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes3.ts, 179, 3)) +>Foo : Symbol(Foo, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 19)) +>bar : Symbol(bar, Decl(inferFromGenericFunctionReturnTypes3.ts, 177, 27)) +>state : Symbol(state, Decl(inferFromGenericFunctionReturnTypes3.ts, 179, 36)) +>State.A : Symbol(State.A, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 12)) +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) +>A : Symbol(State.A, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 12)) +>state : Symbol(state, Decl(inferFromGenericFunctionReturnTypes3.ts, 179, 59)) +>State.B : Symbol(State.B, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 15)) +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) +>B : Symbol(State.B, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 15)) + diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types index e983cc6481924..ccbeb99a11379 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types @@ -450,3 +450,59 @@ const f1: F = () => { ]); }; +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +>foldLeft : (z: U, f: (acc: U, t: boolean) => U) => U +>z : U +>f : (acc: U, t: boolean) => U +>acc : U +>t : boolean + +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error +>res : boolean +>foldLeft(true, (acc, t) => acc && t) : any +>foldLeft : (z: U, f: (acc: U, t: boolean) => U) => U +>true : true +>(acc, t) => acc && t : (acc: true, t: boolean) => boolean +>acc : true +>t : boolean +>acc && t : boolean +>acc : true +>t : boolean + +enum State { A, B } +>State : State +>A : State.A +>B : State.B + +type Foo = { state: State } +>Foo : Foo +>state : State + +declare function bar(f: () => T[]): T[]; +>bar : (f: () => T[]) => T[] +>f : () => T[] + +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error +>x : Foo[] +>bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]) : any +>bar : (f: () => T[]) => T[] +>() => !!true ? [{ state: State.A }] : [{ state: State.B }] : () => { state: State.A; }[] | { state: State.B; }[] +>!!true ? [{ state: State.A }] : [{ state: State.B }] : { state: State; }[] +>!!true : true +>!true : false +>true : true +>[{ state: State.A }] : { state: State; }[] +>{ state: State.A } : { state: State; } +>state : State +>State.A : State.A +>State : typeof State +>A : State.A +>[{ state: State.B }] : { state: State; }[] +>{ state: State.B } : { state: State; } +>state : State +>State.B : State.B +>State : typeof State +>B : State.B +