Merge pull request #29478 from Microsoft/fixContextualReturnTypes

Infer contextual types from generic return types
This commit is contained in:
Anders Hejlsberg 2019-02-01 12:31:08 -08:00 committed by GitHub
commit 607f2ea4de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1899 additions and 30 deletions

View File

@ -14636,18 +14636,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 ? (<TypeReference>source).typeArguments![i] : sourceRestType!, target.typeArguments![i]);
}
if (targetRestType) {
const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : [];
const types = fixedLength < sourceLength ? (<TypeReference>source).typeArguments!.slice(fixedLength, sourceLength) : [];
if (sourceRestType) {
types.push(sourceRestType);
}
@ -17759,19 +17759,49 @@ 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, /*noReductions*/ true);
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 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)) {
const returnMapper = (<InferenceContext>getContextualMapper(node)).returnMapper;
if (returnMapper) {
return instantiateInstantiableTypes(contextualType, returnMapper);
}
}
return contextualType;
}
// 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 {
if (type.flags & TypeFlags.Instantiable) {
return instantiateType(type, mapper);
}
if (type.flags & TypeFlags.Union) {
return getUnionType(map((<UnionType>type).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None);
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(map((<IntersectionType>type).types, t => instantiateInstantiableTypes(t, mapper)));
}
return type;
}
/**
* Woah! Do you really want to use this function?
*
@ -19910,6 +19940,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);
}
}
@ -23020,7 +23053,12 @@ 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);
// 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;
context.contextualMapper = saveContextualMapper;
return result;
@ -23104,13 +23142,10 @@ 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 isConstContext(node) ? getRegularTypeOfLiteralType(type) :
isTypeAssertion(node) ? type :
getWidenedLiteralLikeTypeForContextualType(type, contextualType);
getWidenedLiteralLikeTypeForContextualType(type, instantiateContextualType(arguments.length === 2 ? getContextualType(node) : contextualType, node));
}
function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type {

View File

@ -4370,6 +4370,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 */

View File

@ -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' }
}
}
}
};

View File

@ -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))
}
}
}
};

View File

@ -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"
}
}
}
};

View File

@ -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"
});

View File

@ -18,12 +18,12 @@ declare function mixBar<T>(obj: T): T & Bar;
let fooBar: FooBar = mixBar({
>fooBar : FooBar
>mixBar({ fooProp: "frizzlebizzle"}) : { fooProp: string; } & Bar
>mixBar({ fooProp: "frizzlebizzle"}) : { fooProp: "frizzlebizzle"; } & Bar
>mixBar : <T>(obj: T) => T & Bar
>{ fooProp: "frizzlebizzle"} : { fooProp: string; }
>{ fooProp: "frizzlebizzle"} : { fooProp: "frizzlebizzle"; }
fooProp: "frizzlebizzle"
>fooProp : string
>fooProp : "frizzlebizzle"
>"frizzlebizzle" : "frizzlebizzle"
});

View File

@ -0,0 +1,203 @@
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 (3 errors) ====
// Repros from #5487
function truePromise(): Promise<true> {
return Promise.resolve(true);
}
interface Wrap<T> {
value: T;
}
function wrap<T>(value: T): Wrap<T> {
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<T> = { value: T };
declare function box<T>(value: T): Box<T>;
type WinCondition =
| { type: 'win', player: string }
| { type: 'draw' };
let zz: Box<WinCondition> = box({ type: 'draw' });
type WinType = 'win' | 'draw';
let yy: Box<WinType> = box('draw');
// Repro from #27074
interface OK<T> {
kind: "OK";
value: T;
}
export function ok<T>(value: T): OK<T> {
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<Array<Player>>;
const f1: F = () => {
return Promise.all([
{
name: "David Gomes",
age: 23,
position: "GOALKEEPER",
}, {
name: "Cristiano Ronaldo",
age: 33,
position: "STRIKER",
}
]);
};
// Breaking change repros from #29478
declare function foldLeft<U>(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<T>(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.

View File

@ -0,0 +1,302 @@
//// [inferFromGenericFunctionReturnTypes3.ts]
// Repros from #5487
function truePromise(): Promise<true> {
return Promise.resolve(true);
}
interface Wrap<T> {
value: T;
}
function wrap<T>(value: T): Wrap<T> {
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<T> = { value: T };
declare function box<T>(value: T): Box<T>;
type WinCondition =
| { type: 'win', player: string }
| { type: 'draw' };
let zz: Box<WinCondition> = box({ type: 'draw' });
type WinType = 'win' | 'draw';
let yy: Box<WinType> = box('draw');
// Repro from #27074
interface OK<T> {
kind: "OK";
value: T;
}
export function ok<T>(value: T): OK<T> {
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<Array<Player>>;
const f1: F = () => {
return Promise.all([
{
name: "David Gomes",
age: 23,
position: "GOALKEEPER",
}, {
name: "Cristiano Ronaldo",
age: 33,
position: "STRIKER",
}
]);
};
// Breaking change repros from #29478
declare function foldLeft<U>(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<T>(f: () => T[]): T[];
let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error
//// [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",
}
]);
};
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]
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<T> {
kind: "OK";
value: T;
}
export declare function ok<T>(value: T): OK<T>;
export {};

View File

@ -0,0 +1,461 @@
=== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts ===
// Repros from #5487
function truePromise(): Promise<true> {
>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<T> {
>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<T>(value: T): Wrap<T> {
>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<T> = { 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<T>(value: T): Box<T>;
>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<WinCondition> = 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<WinType> = 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<T> {
>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<T>(value: T): OK<T> {
>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<Array<Player>>;
>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))
}
]);
};
// Breaking change repros from #29478
declare function foldLeft<U>(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<T>(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))

View File

@ -0,0 +1,508 @@
=== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts ===
// Repros from #5487
function truePromise(): Promise<true> {
>truePromise : () => Promise<true>
>true : true
return Promise.resolve(true);
>Promise.resolve(true) : Promise<true>
>Promise.resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
>Promise : PromiseConstructor
>resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
>true : true
}
interface Wrap<T> {
value: T;
>value : T
}
function wrap<T>(value: T): Wrap<T> {
>wrap : <T>(value: T) => Wrap<T>
>value : T
return { value };
>{ value } : { value: T; }
>value : T
}
function wrappedFoo(): Wrap<'foo'> {
>wrappedFoo : () => Wrap<"foo">
return wrap('foo');
>wrap('foo') : Wrap<"foo">
>wrap : <T>(value: T) => Wrap<T>
>'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 : <T>(value: T) => Wrap<T>
>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 : <T>(value: T) => Wrap<T>
>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 : <U>(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 : <U>(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 : <U>(callbackfn: (value: [number, number], index: number, array: [number, number][]) => U, thisArg?: any) => U[]
>arr : [number, number][]
>map : <U>(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 : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
>values : any[]
>map : <U>(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<string, any>
>obj : any
return new Map(Object.keys(obj).map(key => [key, obj[key]]));
>new Map(Object.keys(obj).map(key => [key, obj[key]])) : Map<string, any>
>Map : MapConstructor
>Object.keys(obj).map(key => [key, obj[key]]) : [string, any][]
>Object.keys(obj).map : <U>(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 : <U>(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 : <U>(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]
>[1] : number[]
>1 : 1
>map : <U>(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<T> = { value: T };
>Box : Box<T>
>value : T
declare function box<T>(value: T): Box<T>;
>box : <T>(value: T) => Box<T>
>value : T
type WinCondition =
>WinCondition : WinCondition
| { type: 'win', player: string }
>type : "win"
>player : string
| { type: 'draw' };
>type : "draw"
let zz: Box<WinCondition> = box({ type: 'draw' });
>zz : Box<WinCondition>
>box({ type: 'draw' }) : Box<{ type: "draw"; }>
>box : <T>(value: T) => Box<T>
>{ type: 'draw' } : { type: "draw"; }
>type : "draw"
>'draw' : "draw"
type WinType = 'win' | 'draw';
>WinType : "win" | "draw"
let yy: Box<WinType> = box('draw');
>yy : Box<"win" | "draw">
>box('draw') : Box<"draw">
>box : <T>(value: T) => Box<T>
>'draw' : "draw"
// Repro from #27074
interface OK<T> {
kind: "OK";
>kind : "OK"
value: T;
>value : T
}
export function ok<T>(value: T): OK<T> {
>ok : <T>(value: T) => OK<T>
>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 : <T>(value: T) => OK<T>
>["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 : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>['a', 'b'] : string[]
>'a' : "a"
>'b' : "b"
>map : <U>(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<Array<Player>>;
>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 : { <TAll>(values: Iterable<TAll | PromiseLike<TAll>>): Promise<TAll[]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; <T1, T2, T3, T4, T5, T6, T7, T8>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; <T1, T2, T3, T4, T5, T6, T7>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; <T1, T2, T3, T4, T5, T6>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>; <T1, T2, T3, T4, T5>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>; <T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>; <T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>; <T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>; <T>(values: (T | PromiseLike<T>)[]): Promise<T[]>; }
>Promise : PromiseConstructor
>all : { <TAll>(values: Iterable<TAll | PromiseLike<TAll>>): Promise<TAll[]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; <T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; <T1, T2, T3, T4, T5, T6, T7, T8>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; <T1, T2, T3, T4, T5, T6, T7>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; <T1, T2, T3, T4, T5, T6>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>; <T1, T2, T3, T4, T5>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>; <T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>; <T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>; <T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>; <T>(values: (T | PromiseLike<T>)[]): Promise<T[]>; }
>[ { 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"
}
]);
};
// Breaking change repros from #29478
declare function foldLeft<U>(z: U, f: (acc: U, t: boolean) => U): U;
>foldLeft : <U>(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 : <U>(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<T>(f: () => T[]): T[];
>bar : <T>(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 : <T>(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

View File

@ -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 };

View File

@ -124,10 +124,10 @@ function test<T extends IFoo>() {
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

View File

@ -93,4 +93,30 @@ 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' }
}
}
}
};

View File

@ -0,0 +1,184 @@
// @strict: true
// @target: es6
// @declaration: true
// Repros from #5487
function truePromise(): Promise<true> {
return Promise.resolve(true);
}
interface Wrap<T> {
value: T;
}
function wrap<T>(value: T): Wrap<T> {
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<T> = { value: T };
declare function box<T>(value: T): Box<T>;
type WinCondition =
| { type: 'win', player: string }
| { type: 'draw' };
let zz: Box<WinCondition> = box({ type: 'draw' });
type WinType = 'win' | 'draw';
let yy: Box<WinType> = box('draw');
// Repro from #27074
interface OK<T> {
kind: "OK";
value: T;
}
export function ok<T>(value: T): OK<T> {
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<Array<Player>>;
const f1: F = () => {
return Promise.all([
{
name: "David Gomes",
age: 23,
position: "GOALKEEPER",
}, {
name: "Cristiano Ronaldo",
age: 33,
position: "STRIKER",
}
]);
};
// Breaking change repros from #29478
declare function foldLeft<U>(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<T>(f: () => T[]): T[];
let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error