From 080b3911e78153e897583597469b2ade3adead9c Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Tue, 22 Aug 2017 23:56:03 +0800 Subject: [PATCH 01/25] add type-level function application --- src/compiler/checker.ts | 16 +++- src/compiler/emitter.ts | 8 ++ src/compiler/factory.ts | 16 ++++ src/compiler/parser.ts | 54 ++++++++++-- src/compiler/types.ts | 10 ++- src/compiler/visitor.ts | 10 +++ .../reference/arrayTypeOfTypeOf.errors.txt | 22 ++--- .../baselines/reference/arrayTypeOfTypeOf.js | 4 +- .../reference/invalidTypeOfTarget.errors.txt | 12 ++- .../reference/invalidTypeOfTarget.js | 3 +- .../reference/parserObjectType5.errors.txt | 5 +- .../reference/parserTypeQuery8.errors.txt | 9 +- tests/baselines/reference/parserTypeQuery8.js | 2 +- tests/baselines/reference/typeCall.js | 36 ++++++++ tests/baselines/reference/typeCall.symbols | 86 ++++++++++++++++++ tests/baselines/reference/typeCall.types | 87 +++++++++++++++++++ tests/cases/compiler/typeCall.ts | 31 +++++++ 17 files changed, 373 insertions(+), 38 deletions(-) create mode 100644 tests/baselines/reference/typeCall.js create mode 100644 tests/baselines/reference/typeCall.symbols create mode 100644 tests/baselines/reference/typeCall.types create mode 100644 tests/cases/compiler/typeCall.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d2d3697f175c6..d79ab58473159 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7546,6 +7546,18 @@ namespace ts { return links.resolvedType; } + function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { + const fn = typeToExpression(node.type); + const args = map(node.arguments, typeToExpression); + const callExpr = createCall(fn, node.typeArguments, args); + return checkExpression(callExpr); + } + + // null! as type + function typeToExpression(type: TypeNode): Expression { + return createAsExpression(createNonNullExpression(createNull()), type); + } + function createIndexedAccessType(objectType: Type, indexType: Type) { const type = createType(TypeFlags.IndexedAccess); type.objectType = objectType; @@ -8003,6 +8015,8 @@ namespace ts { return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); case SyntaxKind.TypeOperator: return getTypeFromTypeOperatorNode(node); + case SyntaxKind.TypeCall: + return getTypeFromTypeCallNode(node); case SyntaxKind.IndexedAccessType: return getTypeFromIndexedAccessTypeNode(node); case SyntaxKind.MappedType: @@ -13179,7 +13193,7 @@ namespace ts { return node.contextualType; } const parent = node.parent; - switch (parent.kind) { + switch (parent && parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 5444c618353bd..641f4dbc833d3 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -753,6 +753,8 @@ namespace ts { return emitPropertyAccessExpression(node); case SyntaxKind.ElementAccessExpression: return emitElementAccessExpression(node); + case SyntaxKind.TypeCall: + return emitTypeCall(node); case SyntaxKind.CallExpression: return emitCallExpression(node); case SyntaxKind.NewExpression: @@ -1240,6 +1242,12 @@ namespace ts { write("]"); } + function emitTypeCall(node: TypeCallTypeNode) { + emit(node.type); + emitTypeArguments(node, node.typeArguments); + emitList(node, node.arguments, ListFormat.CallExpressionArguments); + } + function emitCallExpression(node: CallExpression) { emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index daec1bce1e8b5..be310b80cedcf 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -888,6 +888,22 @@ namespace ts { : node; } + export function createTypeCall(type: TypeNode, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { + const node = createSynthesizedNode(SyntaxKind.TypeCall); + node.type = parenthesizeElementTypeMember(type); + node.typeArguments = asNodeArray(typeArguments); + node.arguments = parenthesizeElementTypeMembers(createNodeArray(argumentsArray)); + return node; + } + + export function updateTypeCall(node: TypeCallTypeNode, type: TypeNode, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { + return node.type !== type + || node.typeArguments !== typeArguments + || node.arguments !== argumentsArray + ? updateNode(createTypeCall(type, typeArguments, argumentsArray), node) + : node; + } + export function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { const node = createSynthesizedNode(SyntaxKind.CallExpression); node.expression = parenthesizeForAccess(expression); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a2fe752ad18e9..261a54045bb75 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -170,6 +170,10 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).argumentExpression); + case SyntaxKind.TypeCall: + return visitNode(cbNode, (node).type) || + visitNodes(cbNode, cbNodes, (node).typeArguments) || + visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: return visitNode(cbNode, (node).expression) || @@ -2738,8 +2742,8 @@ namespace ts { return token() === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); } - function parseJSDocPostfixTypeOrHigher(): TypeNode { - const type = parseNonArrayType(); + function parseJSDocPostfixTypeOrHigher(typeNode?: TypeNode): TypeNode { + const type = typeNode || parseNonArrayType(); const kind = getKind(token()); if (!kind) return type; nextToken(); @@ -2761,8 +2765,8 @@ namespace ts { } } - function parseArrayTypeOrHigher(): TypeNode { - let type = parseJSDocPostfixTypeOrHigher(); + function parseArrayTypeOrHigher(typeNode?: TypeNode): TypeNode { + let type = parseJSDocPostfixTypeOrHigher(typeNode); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { if (isStartOfType()) { const node = createNode(SyntaxKind.IndexedAccessType, type.pos); @@ -2794,7 +2798,7 @@ namespace ts { case SyntaxKind.KeyOfKeyword: return parseTypeOperator(SyntaxKind.KeyOfKeyword); } - return parseArrayTypeOrHigher(); + return parseTypeCallRest(); } function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode { @@ -4240,6 +4244,46 @@ namespace ts { } } + // type equivalent of parseCallExpressionRest + function parseTypeCallRest(type?: TypeNode): TypeNode { + while (true) { + type = parseArrayTypeOrHigher(type); + if (token() === SyntaxKind.LessThanToken) { + // See if this is the start of a generic invocation. If so, consume it and + // keep checking for postfix expressions. Otherwise, it's just a '<' that's + // part of an arithmetic expression. Break out so we consume it higher in the + // stack. + const typeArguments = tryParse(parseTypeArgumentsInExpression); + if (!typeArguments) { + return type; + } + + const callExpr = createNode(SyntaxKind.TypeCall, type.pos); + callExpr.type = type; + callExpr.typeArguments = typeArguments; + callExpr.arguments = parseTypeArgumentList(); + type = finishNode(callExpr); + continue; + } + else if (token() === SyntaxKind.OpenParenToken) { + const callExpr = createNode(SyntaxKind.TypeCall, type.pos); + callExpr.type = type; + callExpr.arguments = parseTypeArgumentList(); + type = finishNode(callExpr); + continue; + } + + return type; + } + } + + function parseTypeArgumentList() { + parseExpected(SyntaxKind.OpenParenToken); + const result = parseDelimitedList(ParsingContext.TypeArguments, parseType); + parseExpected(SyntaxKind.CloseParenToken); + return result; + } + function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression { while (true) { expression = parseMemberExpressionRest(expression); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 608bc779042df..df9cc5b01c483 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -240,6 +240,7 @@ namespace ts { IndexedAccessType, MappedType, LiteralType, + TypeCall, // Binding patterns ObjectBindingPattern, ArrayBindingPattern, @@ -398,7 +399,7 @@ namespace ts { FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, FirstTypeNode = TypePredicate, - LastTypeNode = LiteralType, + LastTypeNode = TypeCall, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, FirstToken = Unknown, @@ -1495,6 +1496,13 @@ namespace ts { arguments: NodeArray; } + export interface TypeCallTypeNode extends TypeNode { + kind: SyntaxKind.TypeCall; + type: TypeNode; + typeArguments?: NodeArray; + arguments: NodeArray; + } + // see: https://tc39.github.io/ecma262/#prod-SuperCall export interface SuperCall extends CallExpression { expression: SuperExpression; diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 1ce42199372d8..0592b84a50f03 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -446,6 +446,12 @@ namespace ts { visitNode((node).expression, visitor, isExpression), visitNode((node).argumentExpression, visitor, isExpression)); + case SyntaxKind.TypeCall: + return updateTypeCall(node, + visitNode((node).type, visitor, isTypeNode), + nodesVisitor((node).typeArguments, visitor, isTypeNode), + nodesVisitor((node).arguments, visitor, isTypeNode)); + case SyntaxKind.CallExpression: return updateCall(node, visitNode((node).expression, visitor, isExpression), @@ -1391,6 +1397,10 @@ namespace ts { result = reduceNode((node).expression, cbNode, result); break; + case SyntaxKind.TypeCall: + result = reduceNode((node).type, cbNode, result); + break; + // Enum case SyntaxKind.EnumMember: result = reduceNode((node).name, cbNode, result); diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt b/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt index 1c37f04be72b8..3479bd8044388 100644 --- a/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt +++ b/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt @@ -1,28 +1,16 @@ -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,5): error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,22): error TS1005: '=' expected. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,30): error TS1109: Expression expected. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,5): error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,22): error TS1005: '=' expected. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,32): error TS1109: Expression expected. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,30): error TS1005: '(' expected. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,32): error TS1005: '(' expected. -==== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts (6 errors) ==== +==== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts (2 errors) ==== // array type cannot use typeof. var x = 1; var xs: typeof x[]; // Not an error. This is equivalent to Array var xs2: typeof Array; var xs3: typeof Array; - ~~~ -!!! error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. - ~ -!!! error TS1005: '=' expected. ~ -!!! error TS1109: Expression expected. +!!! error TS1005: '(' expected. var xs4: typeof Array; - ~~~ -!!! error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. - ~ -!!! error TS1005: '=' expected. ~ -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1005: '(' expected. \ No newline at end of file diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.js b/tests/baselines/reference/arrayTypeOfTypeOf.js index f3653346be432..74a50b9cc1fc9 100644 --- a/tests/baselines/reference/arrayTypeOfTypeOf.js +++ b/tests/baselines/reference/arrayTypeOfTypeOf.js @@ -12,5 +12,5 @@ var xs4: typeof Array; var x = 1; var xs; // Not an error. This is equivalent to Array var xs2; -var xs3 = ; -var xs4 = ; +var xs3; +var xs4; diff --git a/tests/baselines/reference/invalidTypeOfTarget.errors.txt b/tests/baselines/reference/invalidTypeOfTarget.errors.txt index e658ab68c81bf..569c36d1f8552 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.errors.txt +++ b/tests/baselines/reference/invalidTypeOfTarget.errors.txt @@ -1,6 +1,8 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(1,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,16): error TS1003: Identifier expected. -tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,24): error TS1005: '=>' expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,18): error TS1005: ',' expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,20): error TS1134: Variable declaration expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,24): error TS1109: Expression expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(3,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(4,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(5,16): error TS1003: Identifier expected. @@ -12,15 +14,19 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(8,16): error TS1003: Identifier expected. -==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (12 errors) ==== +==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (14 errors) ==== var x1: typeof {}; ~ !!! error TS1003: Identifier expected. var x2: typeof (): void; ~ !!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~~~~ +!!! error TS1134: Variable declaration expected. ~ -!!! error TS1005: '=>' expected. +!!! error TS1109: Expression expected. var x3: typeof 1; ~ !!! error TS1003: Identifier expected. diff --git a/tests/baselines/reference/invalidTypeOfTarget.js b/tests/baselines/reference/invalidTypeOfTarget.js index ebc5bb708757c..cda6f90a2f319 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.js +++ b/tests/baselines/reference/invalidTypeOfTarget.js @@ -10,7 +10,8 @@ var x8: typeof /123/; //// [invalidTypeOfTarget.js] var x1 = {}; -var x2 = function () { return ; }; +var x2; +void ; var x3 = 1; var x4 = ''; var x5; diff --git a/tests/baselines/reference/parserObjectType5.errors.txt b/tests/baselines/reference/parserObjectType5.errors.txt index d4db1d2d85c51..2b21a42ecf243 100644 --- a/tests/baselines/reference/parserObjectType5.errors.txt +++ b/tests/baselines/reference/parserObjectType5.errors.txt @@ -1,13 +1,16 @@ tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(2,7): error TS2304: Cannot find name 'B'. +tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,5): error TS2304: Cannot find name 'T'. tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,7): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (3 errors) ==== var v: { A: B ~ !!! error TS2304: Cannot find name 'B'. ; + ~ +!!! error TS2304: Cannot find name 'T'. ~ !!! error TS1005: '(' expected. }; \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.errors.txt b/tests/baselines/reference/parserTypeQuery8.errors.txt index 4a7098ea8fd3f..40c51093d140a 100644 --- a/tests/baselines/reference/parserTypeQuery8.errors.txt +++ b/tests/baselines/reference/parserTypeQuery8.errors.txt @@ -1,16 +1,13 @@ tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,15): error TS2304: Cannot find name 'A'. -tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,16): error TS1005: '=' expected. tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,17): error TS2304: Cannot find name 'B'. -tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,19): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,19): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (4 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (3 errors) ==== var v: typeof A ~ !!! error TS2304: Cannot find name 'A'. - ~ -!!! error TS1005: '=' expected. ~ !!! error TS2304: Cannot find name 'B'. -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1005: '(' expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.js b/tests/baselines/reference/parserTypeQuery8.js index 995ad013c1f0d..f0fd7d6212e76 100644 --- a/tests/baselines/reference/parserTypeQuery8.js +++ b/tests/baselines/reference/parserTypeQuery8.js @@ -2,4 +2,4 @@ var v: typeof A //// [parserTypeQuery8.js] -var v = ; +var v; diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js new file mode 100644 index 0000000000000..7d10ac980ce25 --- /dev/null +++ b/tests/baselines/reference/typeCall.js @@ -0,0 +1,36 @@ +//// [typeCall.ts] +type F1 = () => 1; +type a = F1(); + +type F2 = (a: string) => 1; +type b = F2('foo'); + +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +type k = Id('foo'); + + +//// [typeCall.js] +var a = 'foo'; diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols new file mode 100644 index 0000000000000..cd34250a4f482 --- /dev/null +++ b/tests/baselines/reference/typeCall.symbols @@ -0,0 +1,86 @@ +=== tests/cases/compiler/typeCall.ts === +type F1 = () => 1; +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) + +type a = F1(); +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) + +type F2 = (a: string) => 1; +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) +>a : Symbol(a, Decl(typeCall.ts, 3, 11)) + +type b = F2('foo'); +>b : Symbol(b, Decl(typeCall.ts, 3, 27)) +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) + +interface F3 { +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + + (): 1; + (a: number): 2; +>a : Symbol(a, Decl(typeCall.ts, 8, 5)) + + (a: string): 3; +>a : Symbol(a, Decl(typeCall.ts, 9, 5)) +} +type c = F3(); +>c : Symbol(c, Decl(typeCall.ts, 10, 1)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +type d = F3(123); +>d : Symbol(d, Decl(typeCall.ts, 11, 14)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +type e = F3('foo'); +>e : Symbol(e, Decl(typeCall.ts, 12, 17)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +declare function f4(a: string): 1; +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 15, 20)) + +let a = 'foo'; +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type f = typeof f4(typeof a); +>f : Symbol(f, Decl(typeCall.ts, 16, 14)) +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type g = (() => 1)(); +>g : Symbol(g, Decl(typeCall.ts, 17, 29)) + +type Id = (v: T) => T; +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>v : Symbol(v, Decl(typeCall.ts, 21, 14)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) + +type h = Id(123); +>h : Symbol(h, Decl(typeCall.ts, 21, 25)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +type Wrap = Id(T); +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) + +type i = Wrap<123>; +>i : Symbol(i, Decl(typeCall.ts, 24, 21)) +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) + +type F5 = () => () => { a: () => 1; }; +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) +>a : Symbol(a, Decl(typeCall.ts, 27, 23)) + +type j = F5()()['a'](); +>j : Symbol(j, Decl(typeCall.ts, 27, 38)) +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) + +type k = Id('foo'); +>k : Symbol(k, Decl(typeCall.ts, 28, 23)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types new file mode 100644 index 0000000000000..f0398b1cb6dff --- /dev/null +++ b/tests/baselines/reference/typeCall.types @@ -0,0 +1,87 @@ +=== tests/cases/compiler/typeCall.ts === +type F1 = () => 1; +>F1 : F1 + +type a = F1(); +>a : 1 +>F1 : F1 + +type F2 = (a: string) => 1; +>F2 : F2 +>a : string + +type b = F2('foo'); +>b : 1 +>F2 : F2 + +interface F3 { +>F3 : F3 + + (): 1; + (a: number): 2; +>a : number + + (a: string): 3; +>a : string +} +type c = F3(); +>c : 1 +>F3 : F3 + +type d = F3(123); +>d : 2 +>F3 : F3 + +type e = F3('foo'); +>e : 3 +>F3 : F3 + +declare function f4(a: string): 1; +>f4 : (a: string) => 1 +>a : string + +let a = 'foo'; +>a : string +>'foo' : "foo" + +type f = typeof f4(typeof a); +>f : 1 +>f4 : (a: string) => 1 +>a : string + +type g = (() => 1)(); +>g : 1 + +type Id = (v: T) => T; +>Id : Id +>T : T +>v : T +>T : T +>T : T + +type h = Id(123); +>h : 123 +>Id : Id + +type Wrap = Id(T); +>Wrap : T +>T : T +>Id : Id +>T : T + +type i = Wrap<123>; +>i : 123 +>Wrap : T + +type F5 = () => () => { a: () => 1; }; +>F5 : F5 +>a : () => 1 + +type j = F5()()['a'](); +>j : 1 +>F5 : F5 + +type k = Id('foo'); +>k : any +>Id : Id + diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts new file mode 100644 index 0000000000000..1a867d71c66ff --- /dev/null +++ b/tests/cases/compiler/typeCall.ts @@ -0,0 +1,31 @@ +type F1 = () => 1; +type a = F1(); + +type F2 = (a: string) => 1; +type b = F2('foo'); + +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +type k = Id('foo'); From 312b69e8b76c7266180593af04a19e51cdf2dc99 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Wed, 23 Aug 2017 00:31:49 +0800 Subject: [PATCH 02/25] type calls: add failing test --- tests/baselines/reference/typeCall.js | 21 +++++++- tests/baselines/reference/typeCall.symbols | 60 +++++++++++++++++++++- tests/baselines/reference/typeCall.types | 60 +++++++++++++++++++++- tests/cases/compiler/typeCall.ts | 20 +++++++- 4 files changed, 157 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 7d10ac980ce25..1be051d960c20 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -29,8 +29,27 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -type k = Id('foo'); +type k = Id('foo'); // `any`, explicit type argument fails + +interface IsPrimitive { + (o: T): '0'; + (o: T): '1'; +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + +// explicit type arguments still fail +type genericIsPrimitive = () => IsPrimitive(T); +type stringIsPrimitive2 = genericIsPrimitive(); +type regexpIsPrimitive2 = genericIsPrimitive(); + +// workaround, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known //// [typeCall.js] var a = 'foo'; +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index cd34250a4f482..593e4b2892338 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -80,7 +80,65 @@ type j = F5()()['a'](); >j : Symbol(j, Decl(typeCall.ts, 27, 38)) >F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) -type k = Id('foo'); +type k = Id('foo'); // `any`, explicit type argument fails >k : Symbol(k, Decl(typeCall.ts, 28, 23)) >Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +interface IsPrimitive { +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) + + (o: T): '0'; +>T : Symbol(T, Decl(typeCall.ts, 33, 3)) +>o : Symbol(o, Decl(typeCall.ts, 33, 21)) +>T : Symbol(T, Decl(typeCall.ts, 33, 3)) + + (o: T): '1'; +>T : Symbol(T, Decl(typeCall.ts, 34, 3)) +>o : Symbol(o, Decl(typeCall.ts, 34, 6)) +>T : Symbol(T, Decl(typeCall.ts, 34, 3)) +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +>stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 35, 1)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) + +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +>regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 36, 45)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// explicit type arguments still fail +type genericIsPrimitive = () => IsPrimitive(T); +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 37, 45)) +>T : Symbol(T, Decl(typeCall.ts, 40, 27)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) +>T : Symbol(T, Decl(typeCall.ts, 40, 27)) + +type stringIsPrimitive2 = genericIsPrimitive(); +>stringIsPrimitive2 : Symbol(stringIsPrimitive2, Decl(typeCall.ts, 40, 50)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 37, 45)) + +type regexpIsPrimitive2 = genericIsPrimitive(); +>regexpIsPrimitive2 : Symbol(regexpIsPrimitive2, Decl(typeCall.ts, 41, 55)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 37, 45)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// workaround, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 42, 55)) +>T : Symbol(T, Decl(typeCall.ts, 45, 28)) +>v : Symbol(v, Decl(typeCall.ts, 45, 31)) +>T : Symbol(T, Decl(typeCall.ts, 45, 28)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) +>T : Symbol(T, Decl(typeCall.ts, 45, 28)) + +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +>stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 45, 55)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 42, 55)) + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 46, 54)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 42, 55)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index f0398b1cb6dff..2ffe3492eb4c1 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -81,7 +81,65 @@ type j = F5()()['a'](); >j : 1 >F5 : F5 -type k = Id('foo'); +type k = Id('foo'); // `any`, explicit type argument fails >k : any >Id : Id +interface IsPrimitive { +>IsPrimitive : IsPrimitive + + (o: T): '0'; +>T : T +>o : T +>T : T + + (o: T): '1'; +>T : T +>o : T +>T : T +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +>stringIsPrimitive : "1" +>IsPrimitive : IsPrimitive + +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +>regexpIsPrimitive : "0" +>IsPrimitive : IsPrimitive +>RegExp : RegExp + +// explicit type arguments still fail +type genericIsPrimitive = () => IsPrimitive(T); +>genericIsPrimitive : genericIsPrimitive +>T : T +>IsPrimitive : IsPrimitive +>T : T + +type stringIsPrimitive2 = genericIsPrimitive(); +>stringIsPrimitive2 : any +>genericIsPrimitive : genericIsPrimitive + +type regexpIsPrimitive2 = genericIsPrimitive(); +>regexpIsPrimitive2 : any +>genericIsPrimitive : genericIsPrimitive +>RegExp : RegExp + +// workaround, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : genericIsPrimitive3 +>T : T +>v : T +>T : T +>IsPrimitive : IsPrimitive +>T : T + +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +>stringIsPrimitive3 : "1" +>genericIsPrimitive3 : genericIsPrimitive3 + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : "1" +>genericIsPrimitive3 : genericIsPrimitive3 +>RegExp : RegExp + +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 1a867d71c66ff..27761d1389173 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -28,4 +28,22 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -type k = Id('foo'); +type k = Id('foo'); // `any`, explicit type argument fails + +interface IsPrimitive { + (o: T): '0'; + (o: T): '1'; +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + +// explicit type arguments still fail +type genericIsPrimitive = () => IsPrimitive(T); +type stringIsPrimitive2 = genericIsPrimitive(); +type regexpIsPrimitive2 = genericIsPrimitive(); + +// workaround, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known From c98fe7930546bf93a737cbe774046af3cf2a0d29 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Wed, 23 Aug 2017 15:32:53 +0800 Subject: [PATCH 03/25] disambiguate type argument lists with empty <> --- src/compiler/checker.ts | 10 +- tests/baselines/reference/typeCall.js | 24 +++-- tests/baselines/reference/typeCall.symbols | 116 ++++++++++++++------- tests/baselines/reference/typeCall.types | 72 ++++++++++--- tests/cases/compiler/typeCall.ts | 24 +++-- 5 files changed, 171 insertions(+), 75 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d79ab58473159..4605282da1bcb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6792,7 +6792,7 @@ namespace ts { const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, node)); return createTypeReference(type, typeArguments); } - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); return unknownType; } @@ -6834,7 +6834,7 @@ namespace ts { } return getTypeAliasInstantiation(symbol, typeArguments); } - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); return unknownType; } @@ -6845,7 +6845,7 @@ namespace ts { * Get type from reference to named type that cannot be generic (enum or type parameter) */ function getTypeFromNonGenericTypeReference(node: TypeReferenceType, symbol: Symbol): Type { - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); return unknownType; } @@ -18728,7 +18728,7 @@ namespace ts { } const type = getTypeFromTypeReference(node); if (type !== unknownType) { - if (node.typeArguments) { + if (node.typeArguments && node.typeArguments.length) { // Do type argument local checks only if referenced type is successfully resolved forEach(node.typeArguments, checkSourceElement); if (produceDiagnostics) { @@ -24284,7 +24284,7 @@ namespace ts { function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray): boolean { return checkGrammarForDisallowedTrailingComma(typeArguments) || - checkGrammarForAtLeastOneTypeArgument(node, typeArguments); + false && checkGrammarForAtLeastOneTypeArgument(node, typeArguments); } function checkGrammarForOmittedArgument(args: NodeArray): boolean { diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 1be051d960c20..618847b55522a 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -29,27 +29,35 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -type k = Id('foo'); // `any`, explicit type argument fails +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` + +declare function id(v: T): T; +let l = id('foo'); interface IsPrimitive { - (o: T): '0'; - (o: T): '1'; + (o: object): '0'; + (o: any): '1'; } type stringIsPrimitive = IsPrimitive(string); // '1', ok type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok -// explicit type arguments still fail +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a type genericIsPrimitive = () => IsPrimitive(T); -type stringIsPrimitive2 = genericIsPrimitive(); -type regexpIsPrimitive2 = genericIsPrimitive(); +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +type regexpIsPrimitive2 = genericIsPrimitive<>(); +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known -// workaround, pass as parameters +// alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) // FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); //// [typeCall.js] var a = 'foo'; -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known +var l = id('foo'); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 593e4b2892338..feac9667aa446 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -80,65 +80,103 @@ type j = F5()()['a'](); >j : Symbol(j, Decl(typeCall.ts, 27, 38)) >F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) -type k = Id('foo'); // `any`, explicit type argument fails ->k : Symbol(k, Decl(typeCall.ts, 28, 23)) +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +>k1 : Symbol(k1, Decl(typeCall.ts, 28, 23)) >Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +type k2 = Id<>('foo'); // ok, `string` +>k2 : Symbol(k2, Decl(typeCall.ts, 30, 28)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +declare function id(v: T): T; +>id : Symbol(id, Decl(typeCall.ts, 31, 30)) +>T : Symbol(T, Decl(typeCall.ts, 33, 20)) +>v : Symbol(v, Decl(typeCall.ts, 33, 23)) +>T : Symbol(T, Decl(typeCall.ts, 33, 20)) +>T : Symbol(T, Decl(typeCall.ts, 33, 20)) + +let l = id('foo'); +>l : Symbol(l, Decl(typeCall.ts, 34, 3)) +>id : Symbol(id, Decl(typeCall.ts, 31, 30)) + interface IsPrimitive { ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) - (o: T): '0'; ->T : Symbol(T, Decl(typeCall.ts, 33, 3)) ->o : Symbol(o, Decl(typeCall.ts, 33, 21)) ->T : Symbol(T, Decl(typeCall.ts, 33, 3)) + (o: object): '0'; +>o : Symbol(o, Decl(typeCall.ts, 37, 3)) - (o: T): '1'; ->T : Symbol(T, Decl(typeCall.ts, 34, 3)) ->o : Symbol(o, Decl(typeCall.ts, 34, 6)) ->T : Symbol(T, Decl(typeCall.ts, 34, 3)) + (o: any): '1'; +>o : Symbol(o, Decl(typeCall.ts, 38, 3)) } type stringIsPrimitive = IsPrimitive(string); // '1', ok ->stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 35, 1)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) +>stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 39, 1)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok ->regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 36, 45)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) +>regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 40, 45)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) -// explicit type arguments still fail +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a type genericIsPrimitive = () => IsPrimitive(T); ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 37, 45)) ->T : Symbol(T, Decl(typeCall.ts, 40, 27)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) ->T : Symbol(T, Decl(typeCall.ts, 40, 27)) - -type stringIsPrimitive2 = genericIsPrimitive(); ->stringIsPrimitive2 : Symbol(stringIsPrimitive2, Decl(typeCall.ts, 40, 50)) ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 37, 45)) - -type regexpIsPrimitive2 = genericIsPrimitive(); ->regexpIsPrimitive2 : Symbol(regexpIsPrimitive2, Decl(typeCall.ts, 41, 55)) ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 37, 45)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) +>T : Symbol(T, Decl(typeCall.ts, 44, 27)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) +>T : Symbol(T, Decl(typeCall.ts, 44, 27)) + +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +>stringIsPrimitive2 : Symbol(stringIsPrimitive2, Decl(typeCall.ts, 44, 50)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) + +type regexpIsPrimitive2 = genericIsPrimitive<>(); +>regexpIsPrimitive2 : Symbol(regexpIsPrimitive2, Decl(typeCall.ts, 45, 57)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) -// workaround, pass as parameters +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 42, 55)) ->T : Symbol(T, Decl(typeCall.ts, 45, 28)) ->v : Symbol(v, Decl(typeCall.ts, 45, 31)) ->T : Symbol(T, Decl(typeCall.ts, 45, 28)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 30, 27)) ->T : Symbol(T, Decl(typeCall.ts, 45, 28)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) +>T : Symbol(T, Decl(typeCall.ts, 50, 28)) +>v : Symbol(v, Decl(typeCall.ts, 50, 31)) +>T : Symbol(T, Decl(typeCall.ts, 50, 28)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) +>T : Symbol(T, Decl(typeCall.ts, 50, 28)) type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok ->stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 45, 55)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 42, 55)) +>stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 50, 55)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) ->regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 46, 54)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 42, 55)) +>regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 51, 54)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) // FAILS!, '1' instead of '0', should delay overload selection until type argument is known +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +>map : Symbol(map, Decl(typeCall.ts, 52, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) +>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>O : Symbol(O, Decl(typeCall.ts, 55, 32)) +>fn : Symbol(fn, Decl(typeCall.ts, 55, 51)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 55, 58)) +>O : Symbol(O, Decl(typeCall.ts, 55, 32)) +>P : Symbol(P, Decl(typeCall.ts, 55, 73)) +>O : Symbol(O, Decl(typeCall.ts, 55, 32)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) +>P : Symbol(P, Decl(typeCall.ts, 55, 73)) + +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : Symbol(z, Decl(typeCall.ts, 55, 96)) +>map : Symbol(map, Decl(typeCall.ts, 52, 53)) +>T : Symbol(T, Decl(typeCall.ts, 56, 14)) +>v : Symbol(v, Decl(typeCall.ts, 56, 17)) +>T : Symbol(T, Decl(typeCall.ts, 56, 14)) +>T : Symbol(T, Decl(typeCall.ts, 56, 14)) +>a : Symbol(a, Decl(typeCall.ts, 56, 32)) +>b : Symbol(b, Decl(typeCall.ts, 56, 38)) +>c : Symbol(c, Decl(typeCall.ts, 56, 44)) + diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 2ffe3492eb4c1..b0d3b06102a87 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -81,22 +81,35 @@ type j = F5()()['a'](); >j : 1 >F5 : F5 -type k = Id('foo'); // `any`, explicit type argument fails ->k : any +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +>k1 : any >Id : Id -interface IsPrimitive { ->IsPrimitive : IsPrimitive +type k2 = Id<>('foo'); // ok, `string` +>k2 : string +>Id : Id - (o: T): '0'; +declare function id(v: T): T; +>id : (v: T) => T >T : T ->o : T ->T : T - - (o: T): '1'; +>v : T >T : T ->o : T >T : T + +let l = id('foo'); +>l : string +>id('foo') : string +>id : (v: T) => T +>'foo' : "foo" + +interface IsPrimitive { +>IsPrimitive : IsPrimitive + + (o: object): '0'; +>o : object + + (o: any): '1'; +>o : any } type stringIsPrimitive = IsPrimitive(string); // '1', ok >stringIsPrimitive : "1" @@ -107,23 +120,25 @@ type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok >IsPrimitive : IsPrimitive >RegExp : RegExp -// explicit type arguments still fail +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a type genericIsPrimitive = () => IsPrimitive(T); >genericIsPrimitive : genericIsPrimitive >T : T >IsPrimitive : IsPrimitive >T : T -type stringIsPrimitive2 = genericIsPrimitive(); ->stringIsPrimitive2 : any +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +>stringIsPrimitive2 : "1" >genericIsPrimitive : genericIsPrimitive -type regexpIsPrimitive2 = genericIsPrimitive(); ->regexpIsPrimitive2 : any +type regexpIsPrimitive2 = genericIsPrimitive<>(); +>regexpIsPrimitive2 : "1" >genericIsPrimitive : genericIsPrimitive >RegExp : RegExp -// workaround, pass as parameters +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); >genericIsPrimitive3 : genericIsPrimitive3 >T : T @@ -143,3 +158,28 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) // FAILS!, '1' instead of '0', should delay overload selection until type argument is known +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +>map : map +>Fn : Fn +>Function : Function +>O : O +>fn : Fn +>Fn : Fn +>obj : O +>O : O +>P : P +>O : O +>Fn : Fn +>P : P + +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : { a: any; b: any; c: any; } +>map : map +>T : T +>v : T +>T : T +>T : T +>a : 1 +>b : 2 +>c : 3 + diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 27761d1389173..8591e8b14a33d 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -1,3 +1,5 @@ +// @allowSyntheticDefaultImports: true + type F1 = () => 1; type a = F1(); @@ -28,22 +30,30 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -type k = Id('foo'); // `any`, explicit type argument fails +type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` + +declare function id(v: T): T; +let l = id('foo'); interface IsPrimitive { - (o: T): '0'; - (o: T): '1'; + (o: object): '0'; + (o: any): '1'; } type stringIsPrimitive = IsPrimitive(string); // '1', ok type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok -// explicit type arguments still fail +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a type genericIsPrimitive = () => IsPrimitive(T); -type stringIsPrimitive2 = genericIsPrimitive(); -type regexpIsPrimitive2 = genericIsPrimitive(); +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +type regexpIsPrimitive2 = genericIsPrimitive<>(); +// FAILS!, '1' instead of '0', should delay overload selection until type argument is known -// workaround, pass as parameters +// alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) // FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); From 636b4acae895e6011f1637512213158d95c1f5a2 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Wed, 23 Aug 2017 15:36:00 +0800 Subject: [PATCH 04/25] fix function name --- 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 4605282da1bcb..ea92d0c57bc0b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7547,14 +7547,14 @@ namespace ts { } function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { - const fn = typeToExpression(node.type); - const args = map(node.arguments, typeToExpression); + const fn = typeNodeToExpression(node.type); + const args = map(node.arguments, typeNodeToExpression); const callExpr = createCall(fn, node.typeArguments, args); return checkExpression(callExpr); } // null! as type - function typeToExpression(type: TypeNode): Expression { + function typeNodeToExpression(type: TypeNode): Expression { return createAsExpression(createNonNullExpression(createNull()), type); } From a76ba3838de96da7d4ba8bba220f74b5ad751bbb Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Thu, 24 Aug 2017 15:56:32 +0800 Subject: [PATCH 05/25] show issues: overload selection (#17471), composition --- .../baselines/reference/overloadSelection.js | 12 +++++++ .../reference/overloadSelection.symbols | 26 +++++++++++++++ .../reference/overloadSelection.types | 26 +++++++++++++++ tests/baselines/reference/typeCall.js | 6 ++++ tests/baselines/reference/typeCall.symbols | 31 +++++++++++++++++ tests/baselines/reference/typeCall.types | 33 ++++++++++++++++++- tests/cases/compiler/overloadSelection.ts | 9 +++++ tests/cases/compiler/typeCall.ts | 6 ++++ 8 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/overloadSelection.js create mode 100644 tests/baselines/reference/overloadSelection.symbols create mode 100644 tests/baselines/reference/overloadSelection.types create mode 100644 tests/cases/compiler/overloadSelection.ts diff --git a/tests/baselines/reference/overloadSelection.js b/tests/baselines/reference/overloadSelection.js new file mode 100644 index 0000000000000..a47f65ea88ac1 --- /dev/null +++ b/tests/baselines/reference/overloadSelection.js @@ -0,0 +1,12 @@ +//// [overloadSelection.ts] +interface Match { + (o: object): 0; + (o: any): 1; +} +type Wrap = (v: T) => Match(T); +type A = Wrap(RegExp); +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) + + +//// [overloadSelection.js] +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) diff --git a/tests/baselines/reference/overloadSelection.symbols b/tests/baselines/reference/overloadSelection.symbols new file mode 100644 index 0000000000000..fc3aa50564e30 --- /dev/null +++ b/tests/baselines/reference/overloadSelection.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/overloadSelection.ts === +interface Match { +>Match : Symbol(Match, Decl(overloadSelection.ts, 0, 0)) + + (o: object): 0; +>o : Symbol(o, Decl(overloadSelection.ts, 1, 3)) + + (o: any): 1; +>o : Symbol(o, Decl(overloadSelection.ts, 2, 3)) +} +type Wrap = (v: T) => Match(T); +>Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>v : Symbol(v, Decl(overloadSelection.ts, 4, 25)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) +>Match : Symbol(Match, Decl(overloadSelection.ts, 0, 0)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) + +type A = Wrap(RegExp); +>A : Symbol(A, Decl(overloadSelection.ts, 4, 43)) +>Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) + diff --git a/tests/baselines/reference/overloadSelection.types b/tests/baselines/reference/overloadSelection.types new file mode 100644 index 0000000000000..29bf2c3aa7a8d --- /dev/null +++ b/tests/baselines/reference/overloadSelection.types @@ -0,0 +1,26 @@ +=== tests/cases/compiler/overloadSelection.ts === +interface Match { +>Match : Match + + (o: object): 0; +>o : object + + (o: any): 1; +>o : any +} +type Wrap = (v: T) => Match(T); +>Wrap : Wrap +>T : T +>RegExp : RegExp +>v : T +>T : T +>Match : Match +>T : T + +type A = Wrap(RegExp); +>A : 1 +>Wrap : Wrap +>RegExp : RegExp + +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) + diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 618847b55522a..36baf427ab212 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -56,6 +56,12 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); + +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +type Fn3 = (v: T) => Fn2(Fn1(T)); +type Fn4 = Fn3(1); //// [typeCall.js] diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index feac9667aa446..50e4cde6189a1 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -180,3 +180,34 @@ type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >b : Symbol(b, Decl(typeCall.ts, 56, 38)) >c : Symbol(c, Decl(typeCall.ts, 56, 44)) +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 56, 53)) +>T : Symbol(T, Decl(typeCall.ts, 59, 9)) +>v : Symbol(v, Decl(typeCall.ts, 59, 30)) +>T : Symbol(T, Decl(typeCall.ts, 59, 9)) +>k : Symbol(k, Decl(typeCall.ts, 59, 44)) +>T : Symbol(T, Decl(typeCall.ts, 59, 9)) + +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) +>T : Symbol(T, Decl(typeCall.ts, 60, 9)) +>v : Symbol(v, Decl(typeCall.ts, 60, 15)) +>k : Symbol(k, Decl(typeCall.ts, 60, 21)) +>T : Symbol(T, Decl(typeCall.ts, 60, 9)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(typeCall.ts, 60, 9)) + +type Fn3 = (v: T) => Fn2(Fn1(T)); +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 60, 58)) +>T : Symbol(T, Decl(typeCall.ts, 61, 9)) +>v : Symbol(v, Decl(typeCall.ts, 61, 15)) +>T : Symbol(T, Decl(typeCall.ts, 61, 9)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 56, 53)) +>T : Symbol(T, Decl(typeCall.ts, 61, 9)) + +type Fn4 = Fn3(1); +>Fn4 : Symbol(Fn4, Decl(typeCall.ts, 61, 36)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 60, 58)) + diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index b0d3b06102a87..4c65d69645786 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -116,7 +116,7 @@ type stringIsPrimitive = IsPrimitive(string); // '1', ok >IsPrimitive : IsPrimitive type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok ->regexpIsPrimitive : "0" +>regexpIsPrimitive : "1" >IsPrimitive : IsPrimitive >RegExp : RegExp @@ -183,3 +183,34 @@ type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >b : 2 >c : 3 +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +>Fn1 : Fn1 +>T : T +>v : T[] +>T : T +>k : string +>T : T + +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +>Fn2 : Fn2 +>T : T +>v : { [k: string]: T; } +>k : string +>T : T +>ReadonlyArray : ReadonlyArray +>T : T + +type Fn3 = (v: T) => Fn2(Fn1(T)); +>Fn3 : Fn3 +>T : T +>v : T +>T : T +>Fn2 : Fn2 +>Fn1 : Fn1 +>T : T + +type Fn4 = Fn3(1); +>Fn4 : any +>Fn3 : Fn3 + diff --git a/tests/cases/compiler/overloadSelection.ts b/tests/cases/compiler/overloadSelection.ts new file mode 100644 index 0000000000000..06b5019fd53fb --- /dev/null +++ b/tests/cases/compiler/overloadSelection.ts @@ -0,0 +1,9 @@ +// @allowSyntheticDefaultImports: true + +interface Match { + (o: object): 0; + (o: any): 1; +} +type Wrap = (v: T) => Match(T); +type A = Wrap(RegExp); +// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 8591e8b14a33d..db803444ed8d6 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -57,3 +57,9 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); + +// binary function composition, still fails +type Fn1 = (v: T[]) => { [k: string]: T }; +type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; +type Fn3 = (v: T) => Fn2(Fn1(T)); +type Fn4 = Fn3(1); From 187b6b5f4e4d965defac4244f1227683e038fcd6 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sat, 26 Aug 2017 00:16:27 +0800 Subject: [PATCH 06/25] minimum chaining repro + checks, errors --- src/compiler/checker.ts | 9 + tests/baselines/reference/typeCall.errors.txt | 74 ++++++ tests/baselines/reference/typeCall.js | 97 +++---- tests/baselines/reference/typeCall.symbols | 246 +++++------------- tests/baselines/reference/typeCall.types | 219 ++++------------ tests/cases/compiler/typeCall.ts | 93 +++---- 6 files changed, 292 insertions(+), 446 deletions(-) create mode 100644 tests/baselines/reference/typeCall.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ea92d0c57bc0b..842e830d2c883 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22386,6 +22386,8 @@ namespace ts { return checkBindingElement(node); case SyntaxKind.ClassDeclaration: return checkClassDeclaration(node); + case SyntaxKind.TypeCall: + return checkTypeCallNode(node); case SyntaxKind.InterfaceDeclaration: return checkInterfaceDeclaration(node); case SyntaxKind.TypeAliasDeclaration: @@ -22413,6 +22415,13 @@ namespace ts { } } + function checkTypeCallNode(node: TypeCallTypeNode) { + checkGrammarTypeArguments(node, node.typeArguments); + checkSourceElement(node.type); + forEach(node.arguments, checkSourceElement); + forEach(node.typeArguments, checkSourceElement); + } + // Function and class expression bodies are checked after all statements in the enclosing body. This is // to ensure constructs like the following are permitted: // const foo = function () { diff --git a/tests/baselines/reference/typeCall.errors.txt b/tests/baselines/reference/typeCall.errors.txt new file mode 100644 index 0000000000000..55f653a5edb37 --- /dev/null +++ b/tests/baselines/reference/typeCall.errors.txt @@ -0,0 +1,74 @@ +tests/cases/compiler/typeCall.ts(64,10): error TS2314: Generic type 'Fn2' requires 1 type argument(s). +tests/cases/compiler/typeCall.ts(64,14): error TS2314: Generic type 'Fn1' requires 1 type argument(s). + + +==== tests/cases/compiler/typeCall.ts (2 errors) ==== + // type F1 = () => 1; + // type a = F1(); + + // type F2 = (a: string) => 1; + // type b = F2('foo'); + + // interface F3 { + // (): 1; + // (a: number): 2; + // (a: string): 3; + // } + // type c = F3(); + // type d = F3(123); + // type e = F3('foo'); + + // declare function f4(a: string): 1; + // let a = 'foo'; + // type f = typeof f4(typeof a); + + // type g = (() => 1)(); + + // type Id = (v: T) => T; + // type h = Id(123); + + // type Wrap = Id(T); + // type i = Wrap<123>; + + // type F5 = () => () => { a: () => 1; }; + // type j = F5()()['a'](); + + // type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call + // type k2 = Id<>('foo'); // ok, `string` + + // declare function id(v: T): T; + // let l = id('foo'); + + // interface IsPrimitive { + // (o: object): '0'; + // (o: any): '1'; + // } + // type stringIsPrimitive = IsPrimitive(string); // '1', ok + // type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + + // // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a + // type genericIsPrimitive = () => IsPrimitive(T); + // type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok + // type regexpIsPrimitive2 = genericIsPrimitive<>(); + // // FAILS!, '1' instead of '0', should delay overload selection until type argument is known + + // // alternative, pass as parameters + // type genericIsPrimitive3 = (v: T) => IsPrimitive(T); + // type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok + // type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) + // // FAILS!, '1' instead of '0', should delay overload selection until type argument is known + + // type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) + // type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); + + // binary function composition, still fails + type Fn1 = (v: T[]) => { [k: string]: T }; + type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; + // type Fn3 = (v: T) => Fn2(Fn1(T)); + // type Fn4 = Fn3(1); + type X = Fn2(Fn1(1)); + ~~~ +!!! error TS2314: Generic type 'Fn2' requires 1 type argument(s). + ~~~ +!!! error TS2314: Generic type 'Fn1' requires 1 type argument(s). + \ No newline at end of file diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 36baf427ab212..5b75fc4bfe880 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -1,69 +1,70 @@ //// [typeCall.ts] -type F1 = () => 1; -type a = F1(); +// type F1 = () => 1; +// type a = F1(); -type F2 = (a: string) => 1; -type b = F2('foo'); +// type F2 = (a: string) => 1; +// type b = F2('foo'); -interface F3 { - (): 1; - (a: number): 2; - (a: string): 3; -} -type c = F3(); -type d = F3(123); -type e = F3('foo'); +// interface F3 { +// (): 1; +// (a: number): 2; +// (a: string): 3; +// } +// type c = F3(); +// type d = F3(123); +// type e = F3('foo'); -declare function f4(a: string): 1; -let a = 'foo'; -type f = typeof f4(typeof a); +// declare function f4(a: string): 1; +// let a = 'foo'; +// type f = typeof f4(typeof a); -type g = (() => 1)(); +// type g = (() => 1)(); -type Id = (v: T) => T; -type h = Id(123); +// type Id = (v: T) => T; +// type h = Id(123); -type Wrap = Id(T); -type i = Wrap<123>; +// type Wrap = Id(T); +// type i = Wrap<123>; -type F5 = () => () => { a: () => 1; }; -type j = F5()()['a'](); +// type F5 = () => () => { a: () => 1; }; +// type j = F5()()['a'](); -type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call -type k2 = Id<>('foo'); // ok, `string` +// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +// type k2 = Id<>('foo'); // ok, `string` -declare function id(v: T): T; -let l = id('foo'); +// declare function id(v: T): T; +// let l = id('foo'); -interface IsPrimitive { - (o: object): '0'; - (o: any): '1'; -} -type stringIsPrimitive = IsPrimitive(string); // '1', ok -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +// interface IsPrimitive { +// (o: object): '0'; +// (o: any): '1'; +// } +// type stringIsPrimitive = IsPrimitive(string); // '1', ok +// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -type regexpIsPrimitive2 = genericIsPrimitive<>(); -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known +// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +// type genericIsPrimitive = () => IsPrimitive(T); +// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +// type regexpIsPrimitive2 = genericIsPrimitive<>(); +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known -// alternative, pass as parameters -type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok -type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known +// // alternative, pass as parameters +// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known -type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) -type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); // binary function composition, still fails type Fn1 = (v: T[]) => { [k: string]: T }; type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; -type Fn3 = (v: T) => Fn2(Fn1(T)); -type Fn4 = Fn3(1); +// type Fn3 = (v: T) => Fn2(Fn1(T)); +// type Fn4 = Fn3(1); +type X = Fn2(Fn1(1)); //// [typeCall.js] -var a = 'foo'; -var l = id('foo'); +// type F1 = () => 1; +// type a = F1(); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 50e4cde6189a1..8ce8cb4386642 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -1,188 +1,65 @@ === tests/cases/compiler/typeCall.ts === -type F1 = () => 1; ->F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) - -type a = F1(); ->a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) ->F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) - -type F2 = (a: string) => 1; ->F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) ->a : Symbol(a, Decl(typeCall.ts, 3, 11)) - -type b = F2('foo'); ->b : Symbol(b, Decl(typeCall.ts, 3, 27)) ->F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) - -interface F3 { ->F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) - - (): 1; - (a: number): 2; ->a : Symbol(a, Decl(typeCall.ts, 8, 5)) - - (a: string): 3; ->a : Symbol(a, Decl(typeCall.ts, 9, 5)) -} -type c = F3(); ->c : Symbol(c, Decl(typeCall.ts, 10, 1)) ->F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) - -type d = F3(123); ->d : Symbol(d, Decl(typeCall.ts, 11, 14)) ->F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) - -type e = F3('foo'); ->e : Symbol(e, Decl(typeCall.ts, 12, 17)) ->F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) - -declare function f4(a: string): 1; ->f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) ->a : Symbol(a, Decl(typeCall.ts, 15, 20)) - -let a = 'foo'; ->a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) - -type f = typeof f4(typeof a); ->f : Symbol(f, Decl(typeCall.ts, 16, 14)) ->f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) ->a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) - -type g = (() => 1)(); ->g : Symbol(g, Decl(typeCall.ts, 17, 29)) - -type Id = (v: T) => T; ->Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) ->T : Symbol(T, Decl(typeCall.ts, 21, 11)) ->v : Symbol(v, Decl(typeCall.ts, 21, 14)) ->T : Symbol(T, Decl(typeCall.ts, 21, 11)) ->T : Symbol(T, Decl(typeCall.ts, 21, 11)) - -type h = Id(123); ->h : Symbol(h, Decl(typeCall.ts, 21, 25)) ->Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) - -type Wrap = Id(T); ->Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) ->T : Symbol(T, Decl(typeCall.ts, 24, 10)) ->Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) ->T : Symbol(T, Decl(typeCall.ts, 24, 10)) - -type i = Wrap<123>; ->i : Symbol(i, Decl(typeCall.ts, 24, 21)) ->Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) - -type F5 = () => () => { a: () => 1; }; ->F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) ->a : Symbol(a, Decl(typeCall.ts, 27, 23)) - -type j = F5()()['a'](); ->j : Symbol(j, Decl(typeCall.ts, 27, 38)) ->F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) - -type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call ->k1 : Symbol(k1, Decl(typeCall.ts, 28, 23)) ->Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) - -type k2 = Id<>('foo'); // ok, `string` ->k2 : Symbol(k2, Decl(typeCall.ts, 30, 28)) ->Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) - -declare function id(v: T): T; ->id : Symbol(id, Decl(typeCall.ts, 31, 30)) ->T : Symbol(T, Decl(typeCall.ts, 33, 20)) ->v : Symbol(v, Decl(typeCall.ts, 33, 23)) ->T : Symbol(T, Decl(typeCall.ts, 33, 20)) ->T : Symbol(T, Decl(typeCall.ts, 33, 20)) - -let l = id('foo'); ->l : Symbol(l, Decl(typeCall.ts, 34, 3)) ->id : Symbol(id, Decl(typeCall.ts, 31, 30)) - -interface IsPrimitive { ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) - - (o: object): '0'; ->o : Symbol(o, Decl(typeCall.ts, 37, 3)) - - (o: any): '1'; ->o : Symbol(o, Decl(typeCall.ts, 38, 3)) -} -type stringIsPrimitive = IsPrimitive(string); // '1', ok ->stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 39, 1)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) - -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok ->regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 40, 45)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) ->RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) - -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) ->T : Symbol(T, Decl(typeCall.ts, 44, 27)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) ->T : Symbol(T, Decl(typeCall.ts, 44, 27)) - -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok ->stringIsPrimitive2 : Symbol(stringIsPrimitive2, Decl(typeCall.ts, 44, 50)) ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) - -type regexpIsPrimitive2 = genericIsPrimitive<>(); ->regexpIsPrimitive2 : Symbol(regexpIsPrimitive2, Decl(typeCall.ts, 45, 57)) ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 41, 45)) ->RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) - -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// alternative, pass as parameters -type genericIsPrimitive3 = (v: T) => IsPrimitive(T); ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) ->T : Symbol(T, Decl(typeCall.ts, 50, 28)) ->v : Symbol(v, Decl(typeCall.ts, 50, 31)) ->T : Symbol(T, Decl(typeCall.ts, 50, 28)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 34, 26)) ->T : Symbol(T, Decl(typeCall.ts, 50, 28)) - -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok ->stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 50, 55)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) - -type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) ->regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 51, 54)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 46, 57)) ->RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) - -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) ->map : Symbol(map, Decl(typeCall.ts, 52, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) ->Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->O : Symbol(O, Decl(typeCall.ts, 55, 32)) ->fn : Symbol(fn, Decl(typeCall.ts, 55, 51)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) ->obj : Symbol(obj, Decl(typeCall.ts, 55, 58)) ->O : Symbol(O, Decl(typeCall.ts, 55, 32)) ->P : Symbol(P, Decl(typeCall.ts, 55, 73)) ->O : Symbol(O, Decl(typeCall.ts, 55, 32)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 55, 12)) ->P : Symbol(P, Decl(typeCall.ts, 55, 73)) - -type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : Symbol(z, Decl(typeCall.ts, 55, 96)) ->map : Symbol(map, Decl(typeCall.ts, 52, 53)) ->T : Symbol(T, Decl(typeCall.ts, 56, 14)) ->v : Symbol(v, Decl(typeCall.ts, 56, 17)) ->T : Symbol(T, Decl(typeCall.ts, 56, 14)) ->T : Symbol(T, Decl(typeCall.ts, 56, 14)) ->a : Symbol(a, Decl(typeCall.ts, 56, 32)) ->b : Symbol(b, Decl(typeCall.ts, 56, 38)) ->c : Symbol(c, Decl(typeCall.ts, 56, 44)) +// type F1 = () => 1; +// type a = F1(); + +// type F2 = (a: string) => 1; +// type b = F2('foo'); + +// interface F3 { +// (): 1; +// (a: number): 2; +// (a: string): 3; +// } +// type c = F3(); +// type d = F3(123); +// type e = F3('foo'); + +// declare function f4(a: string): 1; +// let a = 'foo'; +// type f = typeof f4(typeof a); + +// type g = (() => 1)(); + +// type Id = (v: T) => T; +// type h = Id(123); + +// type Wrap = Id(T); +// type i = Wrap<123>; + +// type F5 = () => () => { a: () => 1; }; +// type j = F5()()['a'](); + +// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +// type k2 = Id<>('foo'); // ok, `string` + +// declare function id(v: T): T; +// let l = id('foo'); + +// interface IsPrimitive { +// (o: object): '0'; +// (o: any): '1'; +// } +// type stringIsPrimitive = IsPrimitive(string); // '1', ok +// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + +// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +// type genericIsPrimitive = () => IsPrimitive(T); +// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +// type regexpIsPrimitive2 = genericIsPrimitive<>(); +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// // alternative, pass as parameters +// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known + +// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); // binary function composition, still fails type Fn1 = (v: T[]) => { [k: string]: T }; ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 56, 53)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 0, 0)) >T : Symbol(T, Decl(typeCall.ts, 59, 9)) >v : Symbol(v, Decl(typeCall.ts, 59, 30)) >T : Symbol(T, Decl(typeCall.ts, 59, 9)) @@ -204,10 +81,15 @@ type Fn3 = (v: T) => Fn2(Fn1(T)); >v : Symbol(v, Decl(typeCall.ts, 61, 15)) >T : Symbol(T, Decl(typeCall.ts, 61, 9)) >Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 56, 53)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 0, 0)) >T : Symbol(T, Decl(typeCall.ts, 61, 9)) type Fn4 = Fn3(1); >Fn4 : Symbol(Fn4, Decl(typeCall.ts, 61, 36)) >Fn3 : Symbol(Fn3, Decl(typeCall.ts, 60, 58)) +type X = Fn2(Fn1(1)); +>X : Symbol(X, Decl(typeCall.ts, 62, 18)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 4c65d69645786..16b54684f2f02 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -1,187 +1,61 @@ === tests/cases/compiler/typeCall.ts === -type F1 = () => 1; ->F1 : F1 +// type F1 = () => 1; +// type a = F1(); -type a = F1(); ->a : 1 ->F1 : F1 +// type F2 = (a: string) => 1; +// type b = F2('foo'); -type F2 = (a: string) => 1; ->F2 : F2 ->a : string +// interface F3 { +// (): 1; +// (a: number): 2; +// (a: string): 3; +// } +// type c = F3(); +// type d = F3(123); +// type e = F3('foo'); -type b = F2('foo'); ->b : 1 ->F2 : F2 +// declare function f4(a: string): 1; +// let a = 'foo'; +// type f = typeof f4(typeof a); -interface F3 { ->F3 : F3 +// type g = (() => 1)(); - (): 1; - (a: number): 2; ->a : number +// type Id = (v: T) => T; +// type h = Id(123); - (a: string): 3; ->a : string -} -type c = F3(); ->c : 1 ->F3 : F3 +// type Wrap = Id(T); +// type i = Wrap<123>; -type d = F3(123); ->d : 2 ->F3 : F3 +// type F5 = () => () => { a: () => 1; }; +// type j = F5()()['a'](); -type e = F3('foo'); ->e : 3 ->F3 : F3 +// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +// type k2 = Id<>('foo'); // ok, `string` -declare function f4(a: string): 1; ->f4 : (a: string) => 1 ->a : string +// declare function id(v: T): T; +// let l = id('foo'); -let a = 'foo'; ->a : string ->'foo' : "foo" +// interface IsPrimitive { +// (o: object): '0'; +// (o: any): '1'; +// } +// type stringIsPrimitive = IsPrimitive(string); // '1', ok +// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok -type f = typeof f4(typeof a); ->f : 1 ->f4 : (a: string) => 1 ->a : string +// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +// type genericIsPrimitive = () => IsPrimitive(T); +// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +// type regexpIsPrimitive2 = genericIsPrimitive<>(); +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known -type g = (() => 1)(); ->g : 1 +// // alternative, pass as parameters +// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known -type Id = (v: T) => T; ->Id : Id ->T : T ->v : T ->T : T ->T : T - -type h = Id(123); ->h : 123 ->Id : Id - -type Wrap = Id(T); ->Wrap : T ->T : T ->Id : Id ->T : T - -type i = Wrap<123>; ->i : 123 ->Wrap : T - -type F5 = () => () => { a: () => 1; }; ->F5 : F5 ->a : () => 1 - -type j = F5()()['a'](); ->j : 1 ->F5 : F5 - -type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call ->k1 : any ->Id : Id - -type k2 = Id<>('foo'); // ok, `string` ->k2 : string ->Id : Id - -declare function id(v: T): T; ->id : (v: T) => T ->T : T ->v : T ->T : T ->T : T - -let l = id('foo'); ->l : string ->id('foo') : string ->id : (v: T) => T ->'foo' : "foo" - -interface IsPrimitive { ->IsPrimitive : IsPrimitive - - (o: object): '0'; ->o : object - - (o: any): '1'; ->o : any -} -type stringIsPrimitive = IsPrimitive(string); // '1', ok ->stringIsPrimitive : "1" ->IsPrimitive : IsPrimitive - -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok ->regexpIsPrimitive : "1" ->IsPrimitive : IsPrimitive ->RegExp : RegExp - -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); ->genericIsPrimitive : genericIsPrimitive ->T : T ->IsPrimitive : IsPrimitive ->T : T - -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok ->stringIsPrimitive2 : "1" ->genericIsPrimitive : genericIsPrimitive - -type regexpIsPrimitive2 = genericIsPrimitive<>(); ->regexpIsPrimitive2 : "1" ->genericIsPrimitive : genericIsPrimitive ->RegExp : RegExp - -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// alternative, pass as parameters -type genericIsPrimitive3 = (v: T) => IsPrimitive(T); ->genericIsPrimitive3 : genericIsPrimitive3 ->T : T ->v : T ->T : T ->IsPrimitive : IsPrimitive ->T : T - -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok ->stringIsPrimitive3 : "1" ->genericIsPrimitive3 : genericIsPrimitive3 - -type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) ->regexpIsPrimitive3 : "1" ->genericIsPrimitive3 : genericIsPrimitive3 ->RegExp : RegExp - -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) ->map : map ->Fn : Fn ->Function : Function ->O : O ->fn : Fn ->Fn : Fn ->obj : O ->O : O ->P : P ->O : O ->Fn : Fn ->P : P - -type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : { a: any; b: any; c: any; } ->map : map ->T : T ->v : T ->T : T ->T : T ->a : 1 ->b : 2 ->c : 3 +// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); // binary function composition, still fails type Fn1 = (v: T[]) => { [k: string]: T }; @@ -214,3 +88,8 @@ type Fn4 = Fn3(1); >Fn4 : any >Fn3 : Fn3 +type X = Fn2(Fn1(1)); +>X : any +>Fn2 : Fn2 +>Fn1 : Fn1 + diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index db803444ed8d6..1e3af2a6971b4 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -1,65 +1,66 @@ // @allowSyntheticDefaultImports: true -type F1 = () => 1; -type a = F1(); +// type F1 = () => 1; +// type a = F1(); -type F2 = (a: string) => 1; -type b = F2('foo'); +// type F2 = (a: string) => 1; +// type b = F2('foo'); -interface F3 { - (): 1; - (a: number): 2; - (a: string): 3; -} -type c = F3(); -type d = F3(123); -type e = F3('foo'); +// interface F3 { +// (): 1; +// (a: number): 2; +// (a: string): 3; +// } +// type c = F3(); +// type d = F3(123); +// type e = F3('foo'); -declare function f4(a: string): 1; -let a = 'foo'; -type f = typeof f4(typeof a); +// declare function f4(a: string): 1; +// let a = 'foo'; +// type f = typeof f4(typeof a); -type g = (() => 1)(); +// type g = (() => 1)(); -type Id = (v: T) => T; -type h = Id(123); +// type Id = (v: T) => T; +// type h = Id(123); -type Wrap = Id(T); -type i = Wrap<123>; +// type Wrap = Id(T); +// type i = Wrap<123>; -type F5 = () => () => { a: () => 1; }; -type j = F5()()['a'](); +// type F5 = () => () => { a: () => 1; }; +// type j = F5()()['a'](); -type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call -type k2 = Id<>('foo'); // ok, `string` +// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call +// type k2 = Id<>('foo'); // ok, `string` -declare function id(v: T): T; -let l = id('foo'); +// declare function id(v: T): T; +// let l = id('foo'); -interface IsPrimitive { - (o: object): '0'; - (o: any): '1'; -} -type stringIsPrimitive = IsPrimitive(string); // '1', ok -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +// interface IsPrimitive { +// (o: object): '0'; +// (o: any): '1'; +// } +// type stringIsPrimitive = IsPrimitive(string); // '1', ok +// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -type regexpIsPrimitive2 = genericIsPrimitive<>(); -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known +// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +// type genericIsPrimitive = () => IsPrimitive(T); +// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +// type regexpIsPrimitive2 = genericIsPrimitive<>(); +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known -// alternative, pass as parameters -type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok -type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// FAILS!, '1' instead of '0', should delay overload selection until type argument is known +// // alternative, pass as parameters +// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known -type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) -type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) +// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); // binary function composition, still fails type Fn1 = (v: T[]) => { [k: string]: T }; type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; -type Fn3 = (v: T) => Fn2(Fn1(T)); -type Fn4 = Fn3(1); +// type Fn3 = (v: T) => Fn2(Fn1(T)); +// type Fn4 = Fn3(1); +type X = Fn2(Fn1(1)); From ee110a3c93aba4943b5ab5efb5ecf046b7525c56 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sat, 26 Aug 2017 02:36:37 +0800 Subject: [PATCH 07/25] allow errors on artificial nodes, empty type args --- src/compiler/checker.ts | 15 ++++++++++++--- src/compiler/utilities.ts | 4 ++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 842e830d2c883..670664903198d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6776,7 +6776,7 @@ namespace ts { if (typeParameters) { const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); - if (!isInJavaScriptFile(node) && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { + if (!isInJavaScriptFile(node) && numTypeArguments && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { error(node, minTypeArgumentCount === typeParameters.length ? Diagnostics.Generic_type_0_requires_1_type_argument_s @@ -6822,7 +6822,7 @@ namespace ts { if (typeParameters) { const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); - if (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) { + if (numTypeArguments && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { error(node, minTypeArgumentCount === typeParameters.length ? Diagnostics.Generic_type_0_requires_1_type_argument_s @@ -7549,7 +7549,16 @@ namespace ts { function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { const fn = typeNodeToExpression(node.type); const args = map(node.arguments, typeNodeToExpression); - const callExpr = createCall(fn, node.typeArguments, args); + const callExpr = createCall(fn, node.typeArguments || [], args); + callExpr.parent = node; + callExpr.expression.parent = callExpr; + callExpr.expression.parent = callExpr.expression; + const setArgParents = (arg: Node) => { + arg.parent = callExpr; + (arg as ParenthesizedExpression).expression.parent = arg; + }; + forEach(callExpr.arguments, setArgParents); + forEach(callExpr.typeArguments, setArgParents); return checkExpression(callExpr); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f1a8dfd676b70..693c30b266afb 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -539,6 +539,7 @@ namespace ts { export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic { const sourceFile = getSourceFileOfNode(node); + if (!sourceFile) return createDiagnosticForNodeFromMessageChain(node.parent, messageChain); const span = getErrorSpanForNode(sourceFile, node); return { file: sourceFile, @@ -572,6 +573,9 @@ namespace ts { } export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan { + if (node && node.parent !== node && (!sourceFile || node.pos < 0)) { + return getErrorSpanForNode(sourceFile, node.parent); + } let errorNode = node; switch (node.kind) { case SyntaxKind.SourceFile: From fa39af3ab213f9241be4193646a2e435dfb30cc1 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sat, 26 Aug 2017 18:25:36 +0800 Subject: [PATCH 08/25] switch parent linking to built-in fn.. how to import though? --- src/compiler/checker.ts | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 14f01f1f7c77e..29366e689f80d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7547,15 +7547,8 @@ namespace ts { const fn = typeNodeToExpression(node.type); const args = map(node.arguments, typeNodeToExpression); const callExpr = createCall(fn, node.typeArguments || [], args); + fixupParentReferences(callExpr); callExpr.parent = node; - callExpr.expression.parent = callExpr; - callExpr.expression.parent = callExpr.expression; - const setArgParents = (arg: Node) => { - arg.parent = callExpr; - (arg as ParenthesizedExpression).expression.parent = arg; - }; - forEach(callExpr.arguments, setArgParents); - forEach(callExpr.typeArguments, setArgParents); return checkExpression(callExpr); } @@ -7571,6 +7564,29 @@ namespace ts { return type; } + // Parser.fixupParentReferences + function fixupParentReferences(rootNode: Node) { + let parent: Node = rootNode; + forEachChild(rootNode, visitNode); + return; + function visitNode(n: Node): void { + if (n.parent !== parent) { + n.parent = parent; + const saveParent = parent; + parent = n; + forEachChild(n, visitNode); + if (n.jsDoc) { + for (const jsDoc of n.jsDoc) { + jsDoc.parent = n; + parent = jsDoc; + forEachChild(jsDoc, visitNode); + } + } + parent = saveParent; + } + } + } + function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = indexType.flags & TypeFlags.StringOrNumberLiteral ? From 6591541ad626ace9becc3cc3ee9c866daff52324 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 3 Sep 2017 17:20:34 +0800 Subject: [PATCH 09/25] fix some tests --- src/compiler/checker.ts | 69 +- src/compiler/parser.ts | 72 ++- src/compiler/utilities.ts | 13 +- ...TypingWithGenericAndNonGenericSignature.js | 2 +- ...gWithGenericAndNonGenericSignature.symbols | 2 +- ...ingWithGenericAndNonGenericSignature.types | 2 +- .../emptyGenericParamList.errors.txt | 7 +- .../emptyTypeArgumentList.errors.txt | 11 - .../reference/emptyTypeArgumentList.symbols | 8 + .../reference/emptyTypeArgumentList.types | 9 + .../emptyTypeArgumentListWithNew.errors.txt | 11 - .../emptyTypeArgumentListWithNew.symbols | 8 + .../emptyTypeArgumentListWithNew.types | 9 + .../reference/objectRestNegative.errors.txt | 2 +- .../baselines/reference/objectRestNegative.js | 2 +- .../reference/parserObjectType5.errors.txt | 5 +- .../reference/parserTypeQuery8.errors.txt | 5 +- .../reference/syntaxErrors.errors.txt | 5 +- .../typeAliasDeclarationEmit.symbols | 11 +- .../reference/typeAliasDeclarationEmit.types | 1 - tests/baselines/reference/typeCall.errors.txt | 74 --- tests/baselines/reference/typeCall.js | 251 ++++++-- tests/baselines/reference/typeCall.symbols | 590 ++++++++++++++--- tests/baselines/reference/typeCall.types | 591 ++++++++++++++++-- ...TypingWithGenericAndNonGenericSignature.ts | 2 +- .../compiler/typeAliasDeclarationEmit.ts | 1 + tests/cases/compiler/typeCall.ts | 207 ++++-- .../types/rest/objectRestNegative.ts | 2 +- tests/cases/fourslash/underscoreTypings02.ts | 2 +- 29 files changed, 1539 insertions(+), 435 deletions(-) delete mode 100644 tests/baselines/reference/emptyTypeArgumentList.errors.txt create mode 100644 tests/baselines/reference/emptyTypeArgumentList.symbols create mode 100644 tests/baselines/reference/emptyTypeArgumentList.types delete mode 100644 tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt create mode 100644 tests/baselines/reference/emptyTypeArgumentListWithNew.symbols create mode 100644 tests/baselines/reference/emptyTypeArgumentListWithNew.types delete mode 100644 tests/baselines/reference/typeCall.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 29366e689f80d..e366f322e7ea4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6773,7 +6773,7 @@ namespace ts { if (typeParameters) { const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); - if (!isInJavaScriptFile(node) && numTypeArguments && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { + if (!isInJavaScriptFile(node) && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { error(node, minTypeArgumentCount === typeParameters.length ? Diagnostics.Generic_type_0_requires_1_type_argument_s @@ -6819,7 +6819,7 @@ namespace ts { if (typeParameters) { const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); - if (numTypeArguments && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { + if (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) { error(node, minTypeArgumentCount === typeParameters.length ? Diagnostics.Generic_type_0_requires_1_type_argument_s @@ -7543,13 +7543,21 @@ namespace ts { return links.resolvedType; } - function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { + function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { const fn = typeNodeToExpression(node.type); const args = map(node.arguments, typeNodeToExpression); const callExpr = createCall(fn, node.typeArguments || [], args); - fixupParentReferences(callExpr); callExpr.parent = node; - return checkExpression(callExpr); + callExpr.expression.parent = callExpr; + callExpr.expression.parent = callExpr.expression; + forEach(callExpr.arguments, (arg: Node) => { + arg.parent = callExpr; + (arg as ParenthesizedExpression).expression.parent = arg; + }); + forEach(callExpr.typeArguments, (arg: Node) => { + arg.parent = callExpr; + }); + return checkCallExpression(callExpr); } // null! as type @@ -7564,28 +7572,28 @@ namespace ts { return type; } - // Parser.fixupParentReferences - function fixupParentReferences(rootNode: Node) { - let parent: Node = rootNode; - forEachChild(rootNode, visitNode); - return; - function visitNode(n: Node): void { - if (n.parent !== parent) { - n.parent = parent; - const saveParent = parent; - parent = n; - forEachChild(n, visitNode); - if (n.jsDoc) { - for (const jsDoc of n.jsDoc) { - jsDoc.parent = n; - parent = jsDoc; - forEachChild(jsDoc, visitNode); - } - } - parent = saveParent; - } - } - } + // // Parser.fixupParentReferences + // function fixupParentReferences(rootNode: Node) { + // let parent: Node = rootNode; + // forEachChild(rootNode, visitNode); + // return; + // function visitNode(n: Node): void { + // if (n.parent !== parent) { + // n.parent = parent; + // const saveParent = parent; + // parent = n; + // forEachChild(n, visitNode); + // if (n.jsDoc) { + // for (const jsDoc of n.jsDoc) { + // jsDoc.parent = n; + // parent = jsDoc; + // forEachChild(jsDoc, visitNode); + // } + // } + // parent = saveParent; + // } + // } + // } function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; @@ -15202,7 +15210,7 @@ namespace ts { // the declared number of type parameters, the call has an incorrect arity. const numTypeParameters = length(signature.typeParameters); const minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters); - const hasRightNumberOfTypeArgs = !typeArguments || + const hasRightNumberOfTypeArgs = !(typeArguments && typeArguments.length) || (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); if (!hasRightNumberOfTypeArgs) { return false; @@ -15997,7 +16005,7 @@ namespace ts { candidate = originalCandidate; if (candidate.typeParameters) { let typeArgumentTypes: Type[]; - if (typeArguments) { + if (typeArguments && typeArguments.length) { typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidate.typeParameters, getMinTypeArgumentCount(candidate.typeParameters)); if (!checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)) { candidateForTypeArgumentError = originalCandidate; @@ -18780,7 +18788,7 @@ namespace ts { for (let i = 0; i < typeParameters.length; i++) { const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { - if (!typeArguments) { + if (!(typeArguments && typeArguments.length)) { typeArguments = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, minTypeArgumentCount); mapper = createTypeMapper(typeParameters, typeArguments); } @@ -22506,6 +22514,7 @@ namespace ts { checkSourceElement(node.type); forEach(node.arguments, checkSourceElement); forEach(node.typeArguments, checkSourceElement); + getTypeFromTypeCallNode(node); // construct node and check it (checkCallExpression) } // Function and class expression bodies are checked after all statements in the enclosing body. This is diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f9fa1ec6006a4..6338708e47da6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4247,37 +4247,65 @@ namespace ts { // type equivalent of parseCallExpressionRest function parseTypeCallRest(type?: TypeNode): TypeNode { + // console.log("parseTypeCallRest"); while (true) { type = parseArrayTypeOrHigher(type); - if (token() === SyntaxKind.LessThanToken) { - // See if this is the start of a generic invocation. If so, consume it and - // keep checking for postfix expressions. Otherwise, it's just a '<' that's - // part of an arithmetic expression. Break out so we consume it higher in the - // stack. - const typeArguments = tryParse(parseTypeArgumentsInExpression); - if (!typeArguments) { - return type; + // crap, the type may have parsed a semicolon... + if (!~[SyntaxKind.ThisType, SyntaxKind.ArrayType, SyntaxKind.TupleType, SyntaxKind.TypeOperator, SyntaxKind.LiteralType, SyntaxKind.NullKeyword, SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword, SyntaxKind.AnyKeyword, SyntaxKind.NumberKeyword, SyntaxKind.ObjectKeyword, SyntaxKind.BooleanKeyword, SyntaxKind.StringKeyword, SyntaxKind.SymbolKeyword, SyntaxKind.ThisKeyword, SyntaxKind.VoidKeyword, SyntaxKind.UndefinedKeyword, SyntaxKind.NullKeyword, SyntaxKind.NeverKeyword].indexOf(type.kind)) { + if (token() === SyntaxKind.LessThanToken) { + // See if this is the start of a generic invocation. If so, consume it and + // keep checking for postfix expressions. Otherwise, it's just a '<' that's + // part of an arithmetic expression. Break out so we consume it higher in the + // stack. + const typeArguments = tryParse(parseTypeArgumentsInExpression); + if (!typeArguments) { + return type; + } + + const call = tryParse(() => parseTypeCall(type)); + if (call) { + type = call; + continue; + } + } + else if (token() === SyntaxKind.OpenParenToken) { + const call = tryParse(() => parseTypeCall(type)); + if (call) { + type = call; + continue; + } } - const callExpr = createNode(SyntaxKind.TypeCall, type.pos); - callExpr.type = type; - callExpr.typeArguments = typeArguments; - callExpr.arguments = parseTypeArgumentList(); - type = finishNode(callExpr); - continue; } - else if (token() === SyntaxKind.OpenParenToken) { - const callExpr = createNode(SyntaxKind.TypeCall, type.pos); - callExpr.type = type; - callExpr.arguments = parseTypeArgumentList(); - type = finishNode(callExpr); - continue; - } - return type; } } + function parseTypeCall(type: TypeNode) { + let typeArguments: NodeArray; + if (token() === SyntaxKind.LessThanToken) { + typeArguments = tryParse(parseTypeArgumentsInExpression); + } + + // if we're in what looks like a function declaration, scram + const arg = lookAhead(parseFirstParam); + if (arg && arg.type) { + return undefined; + } + + const args = parseTypeArgumentList(); + const callExpr = createNode(SyntaxKind.TypeCall, type.pos); + callExpr.type = type; + callExpr.typeArguments = typeArguments; + callExpr.arguments = args; + return finishNode(callExpr); + } + + function parseFirstParam() { + parseExpected(SyntaxKind.OpenParenToken); + return parseParameter(); + } + function parseTypeArgumentList() { parseExpected(SyntaxKind.OpenParenToken); const result = parseDelimitedList(ParsingContext.TypeArguments, parseType); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6fef025aa8695..7047a11a9bdb9 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -306,6 +306,9 @@ namespace ts { if (nodeIsMissing(node)) { return ""; } + if (!sourceFile) { + sourceFile = getSourceFileOfNode(node); + } const text = sourceFile.text; return text.substring(includeTrivia ? node.pos : skipTrivia(text, node.pos), node.end); @@ -529,7 +532,12 @@ namespace ts { export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic { const sourceFile = getSourceFileOfNode(node); - return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); + if (!sourceFile || node.pos < 0) { + return createDiagnosticForNode(node.parent, message, arg0, arg1, arg2); + } + else { + return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); + } } export function createDiagnosticForNodeInSourceFile(sourceFile: SourceFile, node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic { @@ -577,6 +585,9 @@ namespace ts { return getErrorSpanForNode(sourceFile, node.parent); } let errorNode = node; + if (node.pos < 0) { + return getErrorSpanForNode(sourceFile, node.parent); + } switch (node.kind) { case SyntaxKind.SourceFile: const pos = skipTrivia(sourceFile.text, 0, /*stopAfterLineBreak*/ false); diff --git a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js index 5ee0c758022da..6358564384c72 100644 --- a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js +++ b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js @@ -2,7 +2,7 @@ //• If e is a FunctionExpression or ArrowFunctionExpression with no type parameters and no parameter or return type annotations, and T is a function type with EXACTLY ONE non - generic call signature, then any inferences made for type parameters referenced by the parameters of T’s call signature are fixed(section 4.12.2) and e is processed with the contextual type T, as described in section 4.9.3. var f2: { - (x: string, y: number): string; + (x: string, y: number): string (x: T, y: U): T }; diff --git a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols index d7ba6f0ddc376..7f9b6e3fb52d8 100644 --- a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols +++ b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols @@ -4,7 +4,7 @@ var f2: { >f2 : Symbol(f2, Decl(contextualTypingWithGenericAndNonGenericSignature.ts, 2, 3)) - (x: string, y: number): string; + (x: string, y: number): string >x : Symbol(x, Decl(contextualTypingWithGenericAndNonGenericSignature.ts, 3, 5)) >y : Symbol(y, Decl(contextualTypingWithGenericAndNonGenericSignature.ts, 3, 15)) diff --git a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types index ca6c5b35f3d0e..b7b66aecdb853 100644 --- a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types +++ b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types @@ -4,7 +4,7 @@ var f2: { >f2 : { (x: string, y: number): string; (x: T, y: U): T; } - (x: string, y: number): string; + (x: string, y: number): string >x : string >y : number diff --git a/tests/baselines/reference/emptyGenericParamList.errors.txt b/tests/baselines/reference/emptyGenericParamList.errors.txt index ed1046d0f4949..c0fe9824ab7c4 100644 --- a/tests/baselines/reference/emptyGenericParamList.errors.txt +++ b/tests/baselines/reference/emptyGenericParamList.errors.txt @@ -1,11 +1,8 @@ tests/cases/compiler/emptyGenericParamList.ts(2,8): error TS2314: Generic type 'I' requires 1 type argument(s). -tests/cases/compiler/emptyGenericParamList.ts(2,9): error TS1099: Type argument list cannot be empty. -==== tests/cases/compiler/emptyGenericParamList.ts (2 errors) ==== +==== tests/cases/compiler/emptyGenericParamList.ts (1 errors) ==== class I {} var x: I<>; ~~~ -!!! error TS2314: Generic type 'I' requires 1 type argument(s). - ~~ -!!! error TS1099: Type argument list cannot be empty. \ No newline at end of file +!!! error TS2314: Generic type 'I' requires 1 type argument(s). \ No newline at end of file diff --git a/tests/baselines/reference/emptyTypeArgumentList.errors.txt b/tests/baselines/reference/emptyTypeArgumentList.errors.txt deleted file mode 100644 index 036f307447b83..0000000000000 --- a/tests/baselines/reference/emptyTypeArgumentList.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/emptyTypeArgumentList.ts(2,1): error TS2558: Expected 1 type arguments, but got 0. -tests/cases/compiler/emptyTypeArgumentList.ts(2,4): error TS1099: Type argument list cannot be empty. - - -==== tests/cases/compiler/emptyTypeArgumentList.ts (2 errors) ==== - function foo() { } - foo<>(); - ~~~~~~~ -!!! error TS2558: Expected 1 type arguments, but got 0. - ~~ -!!! error TS1099: Type argument list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/emptyTypeArgumentList.symbols b/tests/baselines/reference/emptyTypeArgumentList.symbols new file mode 100644 index 0000000000000..efbe5705f4fe8 --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentList.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/emptyTypeArgumentList.ts === +function foo() { } +>foo : Symbol(foo, Decl(emptyTypeArgumentList.ts, 0, 0)) +>T : Symbol(T, Decl(emptyTypeArgumentList.ts, 0, 13)) + +foo<>(); +>foo : Symbol(foo, Decl(emptyTypeArgumentList.ts, 0, 0)) + diff --git a/tests/baselines/reference/emptyTypeArgumentList.types b/tests/baselines/reference/emptyTypeArgumentList.types new file mode 100644 index 0000000000000..bfc11caa3661b --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentList.types @@ -0,0 +1,9 @@ +=== tests/cases/compiler/emptyTypeArgumentList.ts === +function foo() { } +>foo : () => void +>T : T + +foo<>(); +>foo<>() : void +>foo : () => void + diff --git a/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt b/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt deleted file mode 100644 index 648aa7c6c5085..0000000000000 --- a/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/emptyTypeArgumentListWithNew.ts(2,1): error TS2558: Expected 1 type arguments, but got 0. -tests/cases/compiler/emptyTypeArgumentListWithNew.ts(2,8): error TS1099: Type argument list cannot be empty. - - -==== tests/cases/compiler/emptyTypeArgumentListWithNew.ts (2 errors) ==== - class foo { } - new foo<>(); - ~~~~~~~~~~~ -!!! error TS2558: Expected 1 type arguments, but got 0. - ~~ -!!! error TS1099: Type argument list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/emptyTypeArgumentListWithNew.symbols b/tests/baselines/reference/emptyTypeArgumentListWithNew.symbols new file mode 100644 index 0000000000000..34ce38aa47816 --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentListWithNew.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/emptyTypeArgumentListWithNew.ts === +class foo { } +>foo : Symbol(foo, Decl(emptyTypeArgumentListWithNew.ts, 0, 0)) +>T : Symbol(T, Decl(emptyTypeArgumentListWithNew.ts, 0, 10)) + +new foo<>(); +>foo : Symbol(foo, Decl(emptyTypeArgumentListWithNew.ts, 0, 0)) + diff --git a/tests/baselines/reference/emptyTypeArgumentListWithNew.types b/tests/baselines/reference/emptyTypeArgumentListWithNew.types new file mode 100644 index 0000000000000..310b5f7cd142c --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentListWithNew.types @@ -0,0 +1,9 @@ +=== tests/cases/compiler/emptyTypeArgumentListWithNew.ts === +class foo { } +>foo : foo +>T : T + +new foo<>(); +>new foo<>() : foo<{}> +>foo : typeof foo + diff --git a/tests/baselines/reference/objectRestNegative.errors.txt b/tests/baselines/reference/objectRestNegative.errors.txt index ced36a642d605..e919be4f19c68 100644 --- a/tests/baselines/reference/objectRestNegative.errors.txt +++ b/tests/baselines/reference/objectRestNegative.errors.txt @@ -39,7 +39,7 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(17,9): error TS2701: Th return rest; } - let rest: { b: string } + let rest: { b: string }; ({a, ...rest.b + rest.b} = o); ~~~~~~~~~~~~~~~ !!! error TS2701: The target of an object rest assignment must be a variable or a property access. diff --git a/tests/baselines/reference/objectRestNegative.js b/tests/baselines/reference/objectRestNegative.js index 915e0a0e86732..3b02895a5c48d 100644 --- a/tests/baselines/reference/objectRestNegative.js +++ b/tests/baselines/reference/objectRestNegative.js @@ -14,7 +14,7 @@ function generic(t: T) { return rest; } -let rest: { b: string } +let rest: { b: string }; ({a, ...rest.b + rest.b} = o); diff --git a/tests/baselines/reference/parserObjectType5.errors.txt b/tests/baselines/reference/parserObjectType5.errors.txt index 2b21a42ecf243..d4db1d2d85c51 100644 --- a/tests/baselines/reference/parserObjectType5.errors.txt +++ b/tests/baselines/reference/parserObjectType5.errors.txt @@ -1,16 +1,13 @@ tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(2,7): error TS2304: Cannot find name 'B'. -tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,5): error TS2304: Cannot find name 'T'. tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,7): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (3 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (2 errors) ==== var v: { A: B ~ !!! error TS2304: Cannot find name 'B'. ; - ~ -!!! error TS2304: Cannot find name 'T'. ~ !!! error TS1005: '(' expected. }; \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.errors.txt b/tests/baselines/reference/parserTypeQuery8.errors.txt index 40c51093d140a..2034bf9033647 100644 --- a/tests/baselines/reference/parserTypeQuery8.errors.txt +++ b/tests/baselines/reference/parserTypeQuery8.errors.txt @@ -1,13 +1,10 @@ tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,15): error TS2304: Cannot find name 'A'. -tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,17): error TS2304: Cannot find name 'B'. tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,19): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (3 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (2 errors) ==== var v: typeof A ~ !!! error TS2304: Cannot find name 'A'. - ~ -!!! error TS2304: Cannot find name 'B'. !!! error TS1005: '(' expected. \ No newline at end of file diff --git a/tests/baselines/reference/syntaxErrors.errors.txt b/tests/baselines/reference/syntaxErrors.errors.txt index 02ad52a15e519..cb639b6d660b7 100644 --- a/tests/baselines/reference/syntaxErrors.errors.txt +++ b/tests/baselines/reference/syntaxErrors.errors.txt @@ -1,14 +1,11 @@ -tests/cases/conformance/jsdoc/badTypeArguments.js(1,15): error TS1099: Type argument list cannot be empty. tests/cases/conformance/jsdoc/badTypeArguments.js(2,22): error TS1009: Trailing comma not allowed. ==== tests/cases/conformance/jsdoc/dummyType.d.ts (0 errors) ==== declare class C { t: T } -==== tests/cases/conformance/jsdoc/badTypeArguments.js (2 errors) ==== +==== tests/cases/conformance/jsdoc/badTypeArguments.js (1 errors) ==== /** @param {C.<>} x */ - ~~ -!!! error TS1099: Type argument list cannot be empty. /** @param {C.} y */ ~ !!! error TS1009: Trailing comma not allowed. diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.symbols b/tests/baselines/reference/typeAliasDeclarationEmit.symbols index 5f98ea75a5a26..631264fdc8281 100644 --- a/tests/baselines/reference/typeAliasDeclarationEmit.symbols +++ b/tests/baselines/reference/typeAliasDeclarationEmit.symbols @@ -1,13 +1,12 @@ === tests/cases/compiler/typeAliasDeclarationEmit.ts === - export type callback = () => T; >callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 0, 21)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 0, 21)) export type CallbackArray = () => T; ->CallbackArray : Symbol(CallbackArray, Decl(typeAliasDeclarationEmit.ts, 1, 34)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) +>CallbackArray : Symbol(CallbackArray, Decl(typeAliasDeclarationEmit.ts, 0, 34)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 2, 26)) >callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 2, 26)) diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.types b/tests/baselines/reference/typeAliasDeclarationEmit.types index cc7d5f9a3422e..b1b338a0a467d 100644 --- a/tests/baselines/reference/typeAliasDeclarationEmit.types +++ b/tests/baselines/reference/typeAliasDeclarationEmit.types @@ -1,5 +1,4 @@ === tests/cases/compiler/typeAliasDeclarationEmit.ts === - export type callback = () => T; >callback : callback >T : T diff --git a/tests/baselines/reference/typeCall.errors.txt b/tests/baselines/reference/typeCall.errors.txt deleted file mode 100644 index 55f653a5edb37..0000000000000 --- a/tests/baselines/reference/typeCall.errors.txt +++ /dev/null @@ -1,74 +0,0 @@ -tests/cases/compiler/typeCall.ts(64,10): error TS2314: Generic type 'Fn2' requires 1 type argument(s). -tests/cases/compiler/typeCall.ts(64,14): error TS2314: Generic type 'Fn1' requires 1 type argument(s). - - -==== tests/cases/compiler/typeCall.ts (2 errors) ==== - // type F1 = () => 1; - // type a = F1(); - - // type F2 = (a: string) => 1; - // type b = F2('foo'); - - // interface F3 { - // (): 1; - // (a: number): 2; - // (a: string): 3; - // } - // type c = F3(); - // type d = F3(123); - // type e = F3('foo'); - - // declare function f4(a: string): 1; - // let a = 'foo'; - // type f = typeof f4(typeof a); - - // type g = (() => 1)(); - - // type Id = (v: T) => T; - // type h = Id(123); - - // type Wrap = Id(T); - // type i = Wrap<123>; - - // type F5 = () => () => { a: () => 1; }; - // type j = F5()()['a'](); - - // type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call - // type k2 = Id<>('foo'); // ok, `string` - - // declare function id(v: T): T; - // let l = id('foo'); - - // interface IsPrimitive { - // (o: object): '0'; - // (o: any): '1'; - // } - // type stringIsPrimitive = IsPrimitive(string); // '1', ok - // type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok - - // // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a - // type genericIsPrimitive = () => IsPrimitive(T); - // type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok - // type regexpIsPrimitive2 = genericIsPrimitive<>(); - // // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - - // // alternative, pass as parameters - // type genericIsPrimitive3 = (v: T) => IsPrimitive(T); - // type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok - // type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) - // // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - - // type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) - // type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); - - // binary function composition, still fails - type Fn1 = (v: T[]) => { [k: string]: T }; - type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; - // type Fn3 = (v: T) => Fn2(Fn1(T)); - // type Fn4 = Fn3(1); - type X = Fn2(Fn1(1)); - ~~~ -!!! error TS2314: Generic type 'Fn2' requires 1 type argument(s). - ~~~ -!!! error TS2314: Generic type 'Fn1' requires 1 type argument(s). - \ No newline at end of file diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 5b75fc4bfe880..8f8225d218290 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -1,70 +1,211 @@ //// [typeCall.ts] -// type F1 = () => 1; -// type a = F1(); +type F1 = () => 1; +type a = F1(); -// type F2 = (a: string) => 1; -// type b = F2('foo'); +type F2 = (a: string) => 1; +type b = F2('foo'); -// interface F3 { -// (): 1; -// (a: number): 2; -// (a: string): 3; -// } -// type c = F3(); -// type d = F3(123); -// type e = F3('foo'); +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +// type k1 = Id('foo'); +// ^ errors, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` + +declare function id(v: T): T; +let l = id('foo'); + +interface IsPrimitive { + (o: object): '0'; + (o: any): '1'; +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +type regexpIsPrimitive2 = genericIsPrimitive<>(); +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +// type Fn4 = Fn3(1); // errors, ok +let ones = null! as 1[]; +type Fn4b = Fn3(typeof ones); +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +type Fn4c = Fn3(1[]); +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// let x = fn2(fn1(1)); // errors with not assignable, ok +// type X = Fn2(Fn1(1)); // errors with not assignable, ok +let y = fn2(fn1(ones)); +type Y = Fn2(Fn1(1[])); + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +type CallMember any }, K extends keyof T> = T[K](); +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; -// declare function f4(a: string): 1; -// let a = 'foo'; -// type f = typeof f4(typeof a); +type HasKey = ( + { [K in keyof T]: 'true' } & + { [key: string]: 'false' } +)[Key]; -// type g = (() => 1)(); +type HasKindKey any> = HasKey; +type MapHasKey any }, Key extends string> = { + [K in keyof T]: HasKey +}; -// type Id = (v: T) => T; -// type h = Id(123); +type KeyOfCall any> = keyof (T()); -// type Wrap = Id(T); -// type i = Wrap<123>; +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; -// type F5 = () => () => { a: () => 1; }; -// type j = F5()()['a'](); +type Obj = { + x: () => number, + z: () => { kind: 'Just', value: string } +} -// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call -// type k2 = Id<>('foo'); // ok, `string` +type T1 = (() => number)(); +type T7 = CallMember; // fails, got any, want number +type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +type T13 = keyof (() => Obj)(); +type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' +type T15 = Obj['z']()['kind']; +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } -// declare function id(v: T): T; -// let l = id('foo'); +let a1: () => string; +let b1: typeof a1(); +type Assert any> = T(); // fails, eagerly resolved to any +let c1: Assert; // fails, got any, want string -// interface IsPrimitive { -// (o: object): '0'; -// (o: any): '1'; +declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any +infer1(null! as () => number); // fails, got any, want number + +declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any +infer2(null! as { a: () => number }); // fails, got any, want number + +declare function infer3(x: { a: () => T }): T; +infer3(null! as { a: () => number }); +const res3: number = infer3(null! as { a: () => number }); + +declare function infer4(x: T, y: () => T): void; +infer4(5, () => 5); + +function assignability(x: T, y: () => T) { + const a: T = x; + const b: T = y(); +} + +function comparability(x: T, y: () => T) { + x === x; + y === y; + // x === y; // rightfully errors +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; // } -// type stringIsPrimitive = IsPrimitive(string); // '1', ok -// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok - -// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -// type genericIsPrimitive = () => IsPrimitive(T); -// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -// type regexpIsPrimitive2 = genericIsPrimitive<>(); -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// // alternative, pass as parameters -// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok -// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) -// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); - -// binary function composition, still fails -type Fn1 = (v: T[]) => { [k: string]: T }; -type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; -// type Fn3 = (v: T) => Fn2(Fn1(T)); -// type Fn4 = Fn3(1); -type X = Fn2(Fn1(1)); + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } + +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); //// [typeCall.js] -// type F1 = () => 1; -// type a = F1(); +var a = 'foo'; +var l = id('foo'); +var fn1 = null; +var fn2 = null; +// type Fn4 = Fn3(1); // errors, ok +var ones = null; +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// let x = fn2(fn1(1)); // errors with not assignable, ok +// type X = Fn2(Fn1(1)); // errors with not assignable, ok +var y = fn2(fn1(ones)); +var a1; +var b1; +var c1; // fails, got any, want string +infer1(null); // fails, got any, want number +infer2(null); // fails, got any, want number +infer3(null); +var res3 = infer3(null); +infer4(5, function () { return 5; }); +function assignability(x, y) { + var a = x; + var b = y(); +} +function comparability(x, y) { + x === x; + y === y; + // x === y; // rightfully errors +} +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } +// type IdMapped = { [K in keyof T]: T[K] } +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; +// const a: IdMapped = z; +// const b: Partial = z; +// } +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 8ce8cb4386642..ae3d6a2e1b6bb 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -1,95 +1,521 @@ === tests/cases/compiler/typeCall.ts === -// type F1 = () => 1; -// type a = F1(); +type F1 = () => 1; +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) -// type F2 = (a: string) => 1; -// type b = F2('foo'); +type a = F1(); +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) -// interface F3 { -// (): 1; -// (a: number): 2; -// (a: string): 3; -// } -// type c = F3(); -// type d = F3(123); -// type e = F3('foo'); +type F2 = (a: string) => 1; +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) +>a : Symbol(a, Decl(typeCall.ts, 3, 11)) -// declare function f4(a: string): 1; -// let a = 'foo'; -// type f = typeof f4(typeof a); +type b = F2('foo'); +>b : Symbol(b, Decl(typeCall.ts, 3, 27)) +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) -// type g = (() => 1)(); +interface F3 { +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) -// type Id = (v: T) => T; -// type h = Id(123); + (): 1; + (a: number): 2; +>a : Symbol(a, Decl(typeCall.ts, 8, 5)) -// type Wrap = Id(T); -// type i = Wrap<123>; + (a: string): 3; +>a : Symbol(a, Decl(typeCall.ts, 9, 5)) +} +type c = F3(); +>c : Symbol(c, Decl(typeCall.ts, 10, 1)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) -// type F5 = () => () => { a: () => 1; }; -// type j = F5()()['a'](); +type d = F3(123); +>d : Symbol(d, Decl(typeCall.ts, 11, 14)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) -// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call -// type k2 = Id<>('foo'); // ok, `string` +type e = F3('foo'); +>e : Symbol(e, Decl(typeCall.ts, 12, 17)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) -// declare function id(v: T): T; -// let l = id('foo'); +declare function f4(a: string): 1; +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 15, 20)) -// interface IsPrimitive { -// (o: object): '0'; -// (o: any): '1'; -// } -// type stringIsPrimitive = IsPrimitive(string); // '1', ok -// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok - -// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -// type genericIsPrimitive = () => IsPrimitive(T); -// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -// type regexpIsPrimitive2 = genericIsPrimitive<>(); -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// // alternative, pass as parameters -// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok -// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) -// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); - -// binary function composition, still fails -type Fn1 = (v: T[]) => { [k: string]: T }; ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 0, 0)) ->T : Symbol(T, Decl(typeCall.ts, 59, 9)) ->v : Symbol(v, Decl(typeCall.ts, 59, 30)) ->T : Symbol(T, Decl(typeCall.ts, 59, 9)) ->k : Symbol(k, Decl(typeCall.ts, 59, 44)) ->T : Symbol(T, Decl(typeCall.ts, 59, 9)) - -type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) ->T : Symbol(T, Decl(typeCall.ts, 60, 9)) ->v : Symbol(v, Decl(typeCall.ts, 60, 15)) ->k : Symbol(k, Decl(typeCall.ts, 60, 21)) ->T : Symbol(T, Decl(typeCall.ts, 60, 9)) +let a = 'foo'; +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type f = typeof f4(typeof a); +>f : Symbol(f, Decl(typeCall.ts, 16, 14)) +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type g = (() => 1)(); +>g : Symbol(g, Decl(typeCall.ts, 17, 29)) + +type Id = (v: T) => T; +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>v : Symbol(v, Decl(typeCall.ts, 21, 14)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) + +type h = Id(123); +>h : Symbol(h, Decl(typeCall.ts, 21, 25)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +type Wrap = Id(T); +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) + +type i = Wrap<123>; +>i : Symbol(i, Decl(typeCall.ts, 24, 21)) +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) + +type F5 = () => () => { a: () => 1; }; +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) +>a : Symbol(a, Decl(typeCall.ts, 27, 23)) + +type j = F5()()['a'](); +>j : Symbol(j, Decl(typeCall.ts, 27, 38)) +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) + +// type k1 = Id('foo'); +// ^ errors, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` +>k2 : Symbol(k2, Decl(typeCall.ts, 28, 23)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +declare function id(v: T): T; +>id : Symbol(id, Decl(typeCall.ts, 32, 30)) +>T : Symbol(T, Decl(typeCall.ts, 34, 20)) +>v : Symbol(v, Decl(typeCall.ts, 34, 23)) +>T : Symbol(T, Decl(typeCall.ts, 34, 20)) +>T : Symbol(T, Decl(typeCall.ts, 34, 20)) + +let l = id('foo'); +>l : Symbol(l, Decl(typeCall.ts, 35, 3)) +>id : Symbol(id, Decl(typeCall.ts, 32, 30)) + +interface IsPrimitive { +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) + + (o: object): '0'; +>o : Symbol(o, Decl(typeCall.ts, 38, 3)) + + (o: any): '1'; +>o : Symbol(o, Decl(typeCall.ts, 39, 3)) +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +>stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 40, 1)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) + +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +>regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 41, 45)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 42, 45)) +>T : Symbol(T, Decl(typeCall.ts, 45, 27)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) +>T : Symbol(T, Decl(typeCall.ts, 45, 27)) + +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +>stringIsPrimitive2 : Symbol(stringIsPrimitive2, Decl(typeCall.ts, 45, 50)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 42, 45)) + +type regexpIsPrimitive2 = genericIsPrimitive<>(); +>regexpIsPrimitive2 : Symbol(regexpIsPrimitive2, Decl(typeCall.ts, 46, 57)) +>genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 42, 45)) + +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 47, 57)) +>T : Symbol(T, Decl(typeCall.ts, 51, 28)) +>v : Symbol(v, Decl(typeCall.ts, 51, 31)) +>T : Symbol(T, Decl(typeCall.ts, 51, 28)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) +>T : Symbol(T, Decl(typeCall.ts, 51, 28)) + +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +>stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 51, 55)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 47, 57)) + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 52, 54)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 47, 57)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +>map : Symbol(map, Decl(typeCall.ts, 53, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 56, 12)) +>v : Symbol(v, Decl(typeCall.ts, 56, 24)) +>T : Symbol(T, Decl(typeCall.ts, 56, 67)) +>O : Symbol(O, Decl(typeCall.ts, 56, 37)) +>k : Symbol(k, Decl(typeCall.ts, 56, 51)) +>T : Symbol(T, Decl(typeCall.ts, 56, 67)) +>T : Symbol(T, Decl(typeCall.ts, 56, 67)) +>fn : Symbol(fn, Decl(typeCall.ts, 56, 71)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 56, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 56, 78)) +>O : Symbol(O, Decl(typeCall.ts, 56, 37)) +>P : Symbol(P, Decl(typeCall.ts, 56, 93)) +>O : Symbol(O, Decl(typeCall.ts, 56, 37)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 56, 12)) +>O : Symbol(O, Decl(typeCall.ts, 56, 37)) +>P : Symbol(P, Decl(typeCall.ts, 56, 93)) + +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : Symbol(z, Decl(typeCall.ts, 56, 119)) +>map : Symbol(map, Decl(typeCall.ts, 53, 53)) +>T : Symbol(T, Decl(typeCall.ts, 57, 14)) +>v : Symbol(v, Decl(typeCall.ts, 57, 17)) +>T : Symbol(T, Decl(typeCall.ts, 57, 14)) +>T : Symbol(T, Decl(typeCall.ts, 57, 14)) +>a : Symbol(a, Decl(typeCall.ts, 57, 32)) +>b : Symbol(b, Decl(typeCall.ts, 57, 38)) +>c : Symbol(c, Decl(typeCall.ts, 57, 44)) + +// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) +>T1 : Symbol(T1, Decl(typeCall.ts, 61, 12)) +>v1 : Symbol(v1, Decl(typeCall.ts, 61, 31)) +>T1 : Symbol(T1, Decl(typeCall.ts, 61, 12)) +>k : Symbol(k, Decl(typeCall.ts, 61, 47)) +>T1 : Symbol(T1, Decl(typeCall.ts, 61, 12)) + +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) +>T2 : Symbol(T2, Decl(typeCall.ts, 62, 12)) +>v2 : Symbol(v2, Decl(typeCall.ts, 62, 16)) +>k : Symbol(k, Decl(typeCall.ts, 62, 23)) +>T2 : Symbol(T2, Decl(typeCall.ts, 62, 12)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(typeCall.ts, 60, 9)) - -type Fn3 = (v: T) => Fn2(Fn1(T)); ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 60, 58)) ->T : Symbol(T, Decl(typeCall.ts, 61, 9)) ->v : Symbol(v, Decl(typeCall.ts, 61, 15)) ->T : Symbol(T, Decl(typeCall.ts, 61, 9)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 0, 0)) ->T : Symbol(T, Decl(typeCall.ts, 61, 9)) - -type Fn4 = Fn3(1); ->Fn4 : Symbol(Fn4, Decl(typeCall.ts, 61, 36)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 60, 58)) - -type X = Fn2(Fn1(1)); ->X : Symbol(X, Decl(typeCall.ts, 62, 18)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 59, 60)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 0, 0)) +>T2 : Symbol(T2, Decl(typeCall.ts, 62, 12)) + +let fn1 = null! as Fn1; +>fn1 : Symbol(fn1, Decl(typeCall.ts, 63, 3)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) + +let fn2 = null! as Fn2; +>fn2 : Symbol(fn2, Decl(typeCall.ts, 64, 3)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) + +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) +>T3 : Symbol(T3, Decl(typeCall.ts, 65, 12)) +>v3 : Symbol(v3, Decl(typeCall.ts, 65, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 65, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) +>T3 : Symbol(T3, Decl(typeCall.ts, 65, 12)) + +// type Fn4 = Fn3(1); // errors, ok +let ones = null! as 1[]; +>ones : Symbol(ones, Decl(typeCall.ts, 67, 3)) + +type Fn4b = Fn3(typeof ones); +>Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 67, 24)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) +>ones : Symbol(ones, Decl(typeCall.ts, 67, 3)) + +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +type Fn4c = Fn3(1[]); +>Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 68, 29)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) + +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// let x = fn2(fn1(1)); // errors with not assignable, ok +// type X = Fn2(Fn1(1)); // errors with not assignable, ok +let y = fn2(fn1(ones)); +>y : Symbol(y, Decl(typeCall.ts, 74, 3)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 64, 3)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 63, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 67, 3)) + +type Y = Fn2(Fn1(1[])); +>Y : Symbol(Y, Decl(typeCall.ts, 74, 23)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 75, 23)) +>T : Symbol(T, Decl(typeCall.ts, 77, 15)) +>k : Symbol(k, Decl(typeCall.ts, 77, 34)) +>K : Symbol(K, Decl(typeCall.ts, 77, 52)) +>T : Symbol(T, Decl(typeCall.ts, 77, 15)) +>T : Symbol(T, Decl(typeCall.ts, 77, 15)) +>K : Symbol(K, Decl(typeCall.ts, 77, 52)) + +type CallMember any }, K extends keyof T> = T[K](); +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 77, 85)) +>T : Symbol(T, Decl(typeCall.ts, 78, 16)) +>k : Symbol(k, Decl(typeCall.ts, 78, 29)) +>K : Symbol(K, Decl(typeCall.ts, 78, 53)) +>T : Symbol(T, Decl(typeCall.ts, 78, 16)) +>T : Symbol(T, Decl(typeCall.ts, 78, 16)) +>K : Symbol(K, Decl(typeCall.ts, 78, 53)) + +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 78, 82)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>k : Symbol(k, Decl(typeCall.ts, 79, 35)) +>K : Symbol(K, Decl(typeCall.ts, 79, 65)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>K : Symbol(K, Decl(typeCall.ts, 79, 65)) + +type HasKey = ( +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 79, 89)) +>T : Symbol(T, Decl(typeCall.ts, 81, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 81, 14)) + + { [K in keyof T]: 'true' } & +>K : Symbol(K, Decl(typeCall.ts, 82, 5)) +>T : Symbol(T, Decl(typeCall.ts, 81, 12)) + + { [key: string]: 'false' } +>key : Symbol(key, Decl(typeCall.ts, 83, 5)) + +)[Key]; +>Key : Symbol(Key, Decl(typeCall.ts, 81, 14)) + +type HasKindKey any> = HasKey; +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 84, 7)) +>T : Symbol(T, Decl(typeCall.ts, 86, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 79, 89)) +>T : Symbol(T, Decl(typeCall.ts, 86, 16)) + +type MapHasKey any }, Key extends string> = { +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 86, 59)) +>T : Symbol(T, Decl(typeCall.ts, 87, 15)) +>k : Symbol(k, Decl(typeCall.ts, 87, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 87, 52)) + + [K in keyof T]: HasKey +>K : Symbol(K, Decl(typeCall.ts, 88, 5)) +>T : Symbol(T, Decl(typeCall.ts, 87, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 79, 89)) +>T : Symbol(T, Decl(typeCall.ts, 87, 15)) +>K : Symbol(K, Decl(typeCall.ts, 88, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 87, 52)) + +}; + +type KeyOfCall any> = keyof (T()); +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 89, 2)) +>T : Symbol(T, Decl(typeCall.ts, 91, 15)) +>T : Symbol(T, Decl(typeCall.ts, 91, 15)) + +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 91, 50)) +>T : Symbol(T, Decl(typeCall.ts, 93, 12)) +>K : Symbol(K, Decl(typeCall.ts, 93, 38)) +>T : Symbol(T, Decl(typeCall.ts, 93, 12)) +>T : Symbol(T, Decl(typeCall.ts, 93, 12)) +>K : Symbol(K, Decl(typeCall.ts, 93, 38)) + +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 93, 66)) +>T : Symbol(T, Decl(typeCall.ts, 94, 12)) +>k : Symbol(k, Decl(typeCall.ts, 94, 31)) +>K : Symbol(K, Decl(typeCall.ts, 94, 61)) +>T : Symbol(T, Decl(typeCall.ts, 94, 12)) +>T : Symbol(T, Decl(typeCall.ts, 94, 12)) +>K : Symbol(K, Decl(typeCall.ts, 94, 61)) + +type Obj = { +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + + x: () => number, +>x : Symbol(x, Decl(typeCall.ts, 96, 12)) + + z: () => { kind: 'Just', value: string } +>z : Symbol(z, Decl(typeCall.ts, 97, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 98, 14)) +>value : Symbol(value, Decl(typeCall.ts, 98, 28)) +} + +type T1 = (() => number)(); +>T1 : Symbol(T1, Decl(typeCall.ts, 99, 1)) + +type T7 = CallMember; // fails, got any, want number +>T7 : Symbol(T7, Decl(typeCall.ts, 101, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 77, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number +>T8 : Symbol(T8, Decl(typeCall.ts, 102, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 75, 23)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T9 : Symbol(T9, Decl(typeCall.ts, 103, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 78, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T13 = keyof (() => Obj)(); +>T13 : Symbol(T13, Decl(typeCall.ts, 104, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' +>T14 : Symbol(T14, Decl(typeCall.ts, 105, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 89, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T15 = Obj['z']()['kind']; +>T15 : Symbol(T15, Decl(typeCall.ts, 106, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +>T16 : Symbol(T16, Decl(typeCall.ts, 107, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 86, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +>T17 : Symbol(T17, Decl(typeCall.ts, 108, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 91, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T19 : Symbol(T19, Decl(typeCall.ts, 109, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 93, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) + +let a1: () => string; +>a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) + +let b1: typeof a1(); +>b1 : Symbol(b1, Decl(typeCall.ts, 113, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) + +type Assert any> = T(); // fails, eagerly resolved to any +>Assert : Symbol(Assert, Decl(typeCall.ts, 113, 20)) +>T : Symbol(T, Decl(typeCall.ts, 114, 12)) +>T : Symbol(T, Decl(typeCall.ts, 114, 12)) + +let c1: Assert; // fails, got any, want string +>c1 : Symbol(c1, Decl(typeCall.ts, 115, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 113, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) + +declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any +>infer1 : Symbol(infer1, Decl(typeCall.ts, 115, 26)) +>T : Symbol(T, Decl(typeCall.ts, 117, 24)) +>x : Symbol(x, Decl(typeCall.ts, 117, 45)) +>T : Symbol(T, Decl(typeCall.ts, 117, 24)) +>T : Symbol(T, Decl(typeCall.ts, 117, 24)) + +infer1(null! as () => number); // fails, got any, want number +>infer1 : Symbol(infer1, Decl(typeCall.ts, 115, 26)) + +declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any +>infer2 : Symbol(infer2, Decl(typeCall.ts, 118, 30)) +>T : Symbol(T, Decl(typeCall.ts, 120, 24)) +>x : Symbol(x, Decl(typeCall.ts, 120, 45)) +>a : Symbol(a, Decl(typeCall.ts, 120, 49)) +>T : Symbol(T, Decl(typeCall.ts, 120, 24)) +>T : Symbol(T, Decl(typeCall.ts, 120, 24)) + +infer2(null! as { a: () => number }); // fails, got any, want number +>infer2 : Symbol(infer2, Decl(typeCall.ts, 118, 30)) +>a : Symbol(a, Decl(typeCall.ts, 121, 17)) + +declare function infer3(x: { a: () => T }): T; +>infer3 : Symbol(infer3, Decl(typeCall.ts, 121, 37)) +>T : Symbol(T, Decl(typeCall.ts, 123, 24)) +>x : Symbol(x, Decl(typeCall.ts, 123, 27)) +>a : Symbol(a, Decl(typeCall.ts, 123, 31)) +>T : Symbol(T, Decl(typeCall.ts, 123, 24)) +>T : Symbol(T, Decl(typeCall.ts, 123, 24)) + +infer3(null! as { a: () => number }); +>infer3 : Symbol(infer3, Decl(typeCall.ts, 121, 37)) +>a : Symbol(a, Decl(typeCall.ts, 124, 17)) + +const res3: number = infer3(null! as { a: () => number }); +>res3 : Symbol(res3, Decl(typeCall.ts, 125, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 121, 37)) +>a : Symbol(a, Decl(typeCall.ts, 125, 38)) + +declare function infer4(x: T, y: () => T): void; +>infer4 : Symbol(infer4, Decl(typeCall.ts, 125, 58)) +>T : Symbol(T, Decl(typeCall.ts, 127, 24)) +>x : Symbol(x, Decl(typeCall.ts, 127, 27)) +>T : Symbol(T, Decl(typeCall.ts, 127, 24)) +>y : Symbol(y, Decl(typeCall.ts, 127, 32)) +>T : Symbol(T, Decl(typeCall.ts, 127, 24)) + +infer4(5, () => 5); +>infer4 : Symbol(infer4, Decl(typeCall.ts, 125, 58)) + +function assignability(x: T, y: () => T) { +>assignability : Symbol(assignability, Decl(typeCall.ts, 128, 19)) +>T : Symbol(T, Decl(typeCall.ts, 130, 23)) +>x : Symbol(x, Decl(typeCall.ts, 130, 26)) +>T : Symbol(T, Decl(typeCall.ts, 130, 23)) +>y : Symbol(y, Decl(typeCall.ts, 130, 31)) +>T : Symbol(T, Decl(typeCall.ts, 130, 23)) + + const a: T = x; +>a : Symbol(a, Decl(typeCall.ts, 131, 9)) +>T : Symbol(T, Decl(typeCall.ts, 130, 23)) +>x : Symbol(x, Decl(typeCall.ts, 130, 26)) + + const b: T = y(); +>b : Symbol(b, Decl(typeCall.ts, 132, 9)) +>T : Symbol(T, Decl(typeCall.ts, 130, 23)) +>y : Symbol(y, Decl(typeCall.ts, 130, 31)) +} + +function comparability(x: T, y: () => T) { +>comparability : Symbol(comparability, Decl(typeCall.ts, 133, 1)) +>T : Symbol(T, Decl(typeCall.ts, 135, 23)) +>x : Symbol(x, Decl(typeCall.ts, 135, 26)) +>T : Symbol(T, Decl(typeCall.ts, 135, 23)) +>y : Symbol(y, Decl(typeCall.ts, 135, 31)) +>T : Symbol(T, Decl(typeCall.ts, 135, 23)) + + x === x; +>x : Symbol(x, Decl(typeCall.ts, 135, 26)) +>x : Symbol(x, Decl(typeCall.ts, 135, 26)) + + y === y; +>y : Symbol(y, Decl(typeCall.ts, 135, 31)) +>y : Symbol(y, Decl(typeCall.ts, 135, 31)) + + // x === y; // rightfully errors +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } + +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 16b54684f2f02..b547326ef8c9e 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -1,95 +1,558 @@ === tests/cases/compiler/typeCall.ts === -// type F1 = () => 1; -// type a = F1(); +type F1 = () => 1; +>F1 : F1 -// type F2 = (a: string) => 1; -// type b = F2('foo'); +type a = F1(); +>a : 1 +>F1 : F1 -// interface F3 { -// (): 1; -// (a: number): 2; -// (a: string): 3; -// } -// type c = F3(); -// type d = F3(123); -// type e = F3('foo'); +type F2 = (a: string) => 1; +>F2 : F2 +>a : string -// declare function f4(a: string): 1; -// let a = 'foo'; -// type f = typeof f4(typeof a); +type b = F2('foo'); +>b : 1 +>F2 : F2 -// type g = (() => 1)(); +interface F3 { +>F3 : F3 -// type Id = (v: T) => T; -// type h = Id(123); + (): 1; + (a: number): 2; +>a : number -// type Wrap = Id(T); -// type i = Wrap<123>; + (a: string): 3; +>a : string +} +type c = F3(); +>c : 1 +>F3 : F3 -// type F5 = () => () => { a: () => 1; }; -// type j = F5()()['a'](); +type d = F3(123); +>d : 2 +>F3 : F3 -// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call -// type k2 = Id<>('foo'); // ok, `string` +type e = F3('foo'); +>e : 3 +>F3 : F3 -// declare function id(v: T): T; -// let l = id('foo'); +declare function f4(a: string): 1; +>f4 : (a: string) => 1 +>a : string -// interface IsPrimitive { -// (o: object): '0'; -// (o: any): '1'; -// } -// type stringIsPrimitive = IsPrimitive(string); // '1', ok -// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +let a = 'foo'; +>a : string +>'foo' : "foo" + +type f = typeof f4(typeof a); +>f : 1 +>f4 : (a: string) => 1 +>a : string -// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -// type genericIsPrimitive = () => IsPrimitive(T); -// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -// type regexpIsPrimitive2 = genericIsPrimitive<>(); -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known +type g = (() => 1)(); +>g : 1 -// // alternative, pass as parameters -// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok -// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known +type Id = (v: T) => T; +>Id : Id +>T : T +>v : T +>T : T +>T : T -// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) -// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +type h = Id(123); +>h : 123 +>Id : Id -// binary function composition, still fails -type Fn1 = (v: T[]) => { [k: string]: T }; ->Fn1 : Fn1 +type Wrap = Id(T); +>Wrap : T >T : T ->v : T[] +>Id : Id >T : T ->k : string + +type i = Wrap<123>; +>i : 123 +>Wrap : T + +type F5 = () => () => { a: () => 1; }; +>F5 : F5 +>a : () => 1 + +type j = F5()()['a'](); +>j : 1 +>F5 : F5 + +// type k1 = Id('foo'); +// ^ errors, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` +>k2 : "foo" +>Id : Id + +declare function id(v: T): T; +>id : (v: T) => T +>T : T +>v : T >T : T +>T : T + +let l = id('foo'); +>l : string +>id('foo') : string +>id : (v: T) => T +>'foo' : "foo" + +interface IsPrimitive { +>IsPrimitive : IsPrimitive + + (o: object): '0'; +>o : object + + (o: any): '1'; +>o : any +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +>stringIsPrimitive : "1" +>IsPrimitive : IsPrimitive -type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; ->Fn2 : Fn2 +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +>regexpIsPrimitive : "0" +>IsPrimitive : IsPrimitive +>RegExp : RegExp + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +>genericIsPrimitive : genericIsPrimitive +>T : T +>IsPrimitive : IsPrimitive +>T : T + +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +>stringIsPrimitive2 : "1" +>genericIsPrimitive : genericIsPrimitive + +type regexpIsPrimitive2 = genericIsPrimitive<>(); +>regexpIsPrimitive2 : "1" +>genericIsPrimitive : genericIsPrimitive + +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : genericIsPrimitive3 +>T : T +>v : T +>T : T +>IsPrimitive : IsPrimitive >T : T ->v : { [k: string]: T; } + +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +>stringIsPrimitive3 : "1" +>genericIsPrimitive3 : genericIsPrimitive3 + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : "1" +>genericIsPrimitive3 : genericIsPrimitive3 +>RegExp : RegExp + +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +>map : map +>Fn : Fn +>v : T +>T : T +>O : O >k : string >T : T ->ReadonlyArray : ReadonlyArray >T : T +>fn : Fn +>Fn : Fn +>obj : O +>O : O +>P : P +>O : O +>Fn : Fn +>O : O +>P : P -type Fn3 = (v: T) => Fn2(Fn1(T)); ->Fn3 : Fn3 +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : { a: any; b: any; c: any; } +>map : map >T : T >v : T >T : T ->Fn2 : Fn2 ->Fn1 : Fn1 +>T : T +>a : 1 +>b : 2 +>c : 3 + +// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +>Fn1 : Fn1 +>T1 : T1 +>v1 : T1[] +>T1 : T1 +>k : string +>T1 : T1 + +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +>Fn2 : Fn2 +>T2 : T2 +>v2 : { [k: string]: T2; } +>k : string +>T2 : T2 +>ReadonlyArray : ReadonlyArray +>T2 : T2 + +let fn1 = null! as Fn1; +>fn1 : Fn1 +>null! as Fn1 : Fn1 +>null! : never +>null : null +>Fn1 : Fn1 + +let fn2 = null! as Fn2; +>fn2 : Fn2 +>null! as Fn2 : Fn2 +>null! : never +>null : null +>Fn2 : Fn2 + +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +>Fn3 : Fn3 +>T3 : T3 +>v3 : T3 +>T3 : T3 +>Fn2 : Fn2 +>Fn1 : Fn1 +>T3 : T3 + +// type Fn4 = Fn3(1); // errors, ok +let ones = null! as 1[]; +>ones : 1[] +>null! as 1[] : 1[] +>null! : never +>null : null + +type Fn4b = Fn3(typeof ones); +>Fn4b : ReadonlyArray +>Fn3 : Fn3 +>ones : 1[] + +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +type Fn4c = Fn3(1[]); +>Fn4c : ReadonlyArray +>Fn3 : Fn3 + +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// let x = fn2(fn1(1)); // errors with not assignable, ok +// type X = Fn2(Fn1(1)); // errors with not assignable, ok +let y = fn2(fn1(ones)); +>y : ReadonlyArray<1> +>fn2(fn1(ones)) : ReadonlyArray<1> +>fn2 : Fn2 +>fn1(ones) : { [k: string]: 1; } +>fn1 : Fn1 +>ones : 1[] + +type Y = Fn2(Fn1(1[])); +>Y : ReadonlyArray<1> +>Fn2 : Fn2 +>Fn1 : Fn1 + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +>IndexCall : { [k: string]: any; }[K] +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type CallMember any }, K extends keyof T> = T[K](); +>CallMember : any +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; +>MappedMemberCall : MappedMemberCall +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type HasKey = ( +>HasKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })[Key] +>T : T +>Key : Key + + { [K in keyof T]: 'true' } & +>K : K +>T : T + + { [key: string]: 'false' } +>key : string + +)[Key]; +>Key : Key + +type HasKindKey any> = HasKey; +>HasKindKey : any +>T : T +>HasKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })[Key] +>T : T + +type MapHasKey any }, Key extends string> = { +>MapHasKey : MapHasKey +>T : T +>k : string +>Key : Key + + [K in keyof T]: HasKey +>K : K +>T : T +>HasKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })[Key] +>T : T +>K : K +>Key : Key + +}; + +type KeyOfCall any> = keyof (T()); +>KeyOfCall : string +>T : T +>T : T + +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +>Strip1 : Strip1 +>T : T +>K : K +>T : T +>T : T +>K : K + +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; +>Strip2 : Strip2 +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type Obj = { +>Obj : Obj + + x: () => number, +>x : () => number + + z: () => { kind: 'Just', value: string } +>z : () => { kind: "Just"; value: string; } +>kind : "Just" +>value : string +} + +type T1 = (() => number)(); +>T1 : number + +type T7 = CallMember; // fails, got any, want number +>T7 : any +>CallMember : any +>Obj : Obj + +type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number +>T8 : any +>IndexCall : { [k: string]: any; }[K] +>Obj : Obj + +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T9 : MappedMemberCall +>MappedMemberCall : MappedMemberCall +>Obj : Obj + +type T13 = keyof (() => Obj)(); +>T13 : "x" | "z" +>Obj : Obj + +type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' +>T14 : string +>KeyOfCall : string +>Obj : Obj + +type T15 = Obj['z']()['kind']; +>T15 : "Just" +>Obj : Obj + +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +>T16 : MapHasKey +>MapHasKey : MapHasKey +>Obj : Obj + +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +>T17 : Strip1<() => Obj> +>Strip1 : Strip1 +>Obj : Obj + +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T19 : Strip2<() => Obj> +>Strip2 : Strip2 +>Obj : Obj + +let a1: () => string; +>a1 : () => string + +let b1: typeof a1(); +>b1 : string +>a1 : () => string + +type Assert any> = T(); // fails, eagerly resolved to any +>Assert : any +>T : T +>T : T + +let c1: Assert; // fails, got any, want string +>c1 : any +>Assert : any +>a1 : () => string + +declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any +>infer1 : any>(x: T) => any +>T : T +>x : T +>T : T >T : T -type Fn4 = Fn3(1); ->Fn4 : any ->Fn3 : Fn3 +infer1(null! as () => number); // fails, got any, want number +>infer1(null! as () => number) : any +>infer1 : any>(x: T) => any +>null! as () => number : () => number +>null! : never +>null : null + +declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any +>infer2 : any>(x: { a: T; }) => any +>T : T +>x : { a: T; } +>a : T +>T : T +>T : T + +infer2(null! as { a: () => number }); // fails, got any, want number +>infer2(null! as { a: () => number }) : any +>infer2 : any>(x: { a: T; }) => any +>null! as { a: () => number } : { a: () => number; } +>null! : never +>null : null +>a : () => number + +declare function infer3(x: { a: () => T }): T; +>infer3 : (x: { a: () => T; }) => T +>T : T +>x : { a: () => T; } +>a : () => T +>T : T +>T : T + +infer3(null! as { a: () => number }); +>infer3(null! as { a: () => number }) : number +>infer3 : (x: { a: () => T; }) => T +>null! as { a: () => number } : { a: () => number; } +>null! : never +>null : null +>a : () => number + +const res3: number = infer3(null! as { a: () => number }); +>res3 : number +>infer3(null! as { a: () => number }) : number +>infer3 : (x: { a: () => T; }) => T +>null! as { a: () => number } : { a: () => number; } +>null! : never +>null : null +>a : () => number + +declare function infer4(x: T, y: () => T): void; +>infer4 : (x: T, y: () => T) => void +>T : T +>x : T +>T : T +>y : () => T +>T : T + +infer4(5, () => 5); +>infer4(5, () => 5) : void +>infer4 : (x: T, y: () => T) => void +>5 : 5 +>() => 5 : () => number +>5 : 5 + +function assignability(x: T, y: () => T) { +>assignability : (x: T, y: () => T) => void +>T : T +>x : T +>T : T +>y : () => T +>T : T + + const a: T = x; +>a : T +>T : T +>x : T + + const b: T = y(); +>b : T +>T : T +>y() : T +>y : () => T +} + +function comparability(x: T, y: () => T) { +>comparability : (x: T, y: () => T) => void +>T : T +>x : T +>T : T +>y : () => T +>T : T + + x === x; +>x === x : boolean +>x : T +>x : T + + y === y; +>y === y : boolean +>y : () => T +>y : () => T + + // x === y; // rightfully errors +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } -type X = Fn2(Fn1(1)); ->X : any ->Fn2 : Fn2 ->Fn1 : Fn1 +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); diff --git a/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts b/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts index d480bf16b82d8..2faf17c66bbd9 100644 --- a/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts +++ b/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts @@ -1,7 +1,7 @@ //• If e is a FunctionExpression or ArrowFunctionExpression with no type parameters and no parameter or return type annotations, and T is a function type with EXACTLY ONE non - generic call signature, then any inferences made for type parameters referenced by the parameters of T’s call signature are fixed(section 4.12.2) and e is processed with the contextual type T, as described in section 4.9.3. var f2: { - (x: string, y: number): string; + (x: string, y: number): string (x: T, y: U): T }; diff --git a/tests/cases/compiler/typeAliasDeclarationEmit.ts b/tests/cases/compiler/typeAliasDeclarationEmit.ts index be7e40453f60d..4edfd36775c7e 100644 --- a/tests/cases/compiler/typeAliasDeclarationEmit.ts +++ b/tests/cases/compiler/typeAliasDeclarationEmit.ts @@ -1,6 +1,7 @@ // @target: ES5 // @module: AMD // @declaration: true +// @allowSyntheticDefaultImports: true export type callback = () => T; diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 1e3af2a6971b4..9c18d5cab209c 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -1,66 +1,167 @@ // @allowSyntheticDefaultImports: true +// @strictNullChecks: true +// @noimplicitany: true -// type F1 = () => 1; -// type a = F1(); +type F1 = () => 1; +type a = F1(); -// type F2 = (a: string) => 1; -// type b = F2('foo'); +type F2 = (a: string) => 1; +type b = F2('foo'); -// interface F3 { -// (): 1; -// (a: number): 2; -// (a: string): 3; -// } -// type c = F3(); -// type d = F3(123); -// type e = F3('foo'); +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +// type k1 = Id('foo'); +// ^ errors, `` is part of the type reference, not the function call +type k2 = Id<>('foo'); // ok, `string` + +declare function id(v: T): T; +let l = id('foo'); + +interface IsPrimitive { + (o: object): '0'; + (o: any): '1'; +} +type stringIsPrimitive = IsPrimitive(string); // '1', ok +type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok + +// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a +type genericIsPrimitive = () => IsPrimitive(T); +type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok +type regexpIsPrimitive2 = genericIsPrimitive<>(); +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +// type Fn4 = Fn3(1); // errors, ok +let ones = null! as 1[]; +type Fn4b = Fn3(typeof ones); +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +type Fn4c = Fn3(1[]); +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// let x = fn2(fn1(1)); // errors with not assignable, ok +// type X = Fn2(Fn1(1)); // errors with not assignable, ok +let y = fn2(fn1(ones)); +type Y = Fn2(Fn1(1[])); + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +type CallMember any }, K extends keyof T> = T[K](); +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; -// declare function f4(a: string): 1; -// let a = 'foo'; -// type f = typeof f4(typeof a); +type HasKey = ( + { [K in keyof T]: 'true' } & + { [key: string]: 'false' } +)[Key]; -// type g = (() => 1)(); +type HasKindKey any> = HasKey; +type MapHasKey any }, Key extends string> = { + [K in keyof T]: HasKey +}; -// type Id = (v: T) => T; -// type h = Id(123); +type KeyOfCall any> = keyof (T()); -// type Wrap = Id(T); -// type i = Wrap<123>; +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; -// type F5 = () => () => { a: () => 1; }; -// type j = F5()()['a'](); +type Obj = { + x: () => number, + z: () => { kind: 'Just', value: string } +} -// type k1 = Id('foo'); // `any`, `` is part of the type reference, not the function call -// type k2 = Id<>('foo'); // ok, `string` +type T1 = (() => number)(); +type T7 = CallMember; // fails, got any, want number +type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +type T13 = keyof (() => Obj)(); +type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' +type T15 = Obj['z']()['kind']; +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } -// declare function id(v: T): T; -// let l = id('foo'); +let a1: () => string; +let b1: typeof a1(); +type Assert any> = T(); // fails, eagerly resolved to any +let c1: Assert; // fails, got any, want string -// interface IsPrimitive { -// (o: object): '0'; -// (o: any): '1'; +declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any +infer1(null! as () => number); // fails, got any, want number + +declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any +infer2(null! as { a: () => number }); // fails, got any, want number + +declare function infer3(x: { a: () => T }): T; +infer3(null! as { a: () => number }); +const res3: number = infer3(null! as { a: () => number }); + +declare function infer4(x: T, y: () => T): void; +infer4(5, () => 5); + +function assignability(x: T, y: () => T) { + const a: T = x; + const b: T = y(); +} + +function comparability(x: T, y: () => T) { + x === x; + y === y; + // x === y; // rightfully errors +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; // } -// type stringIsPrimitive = IsPrimitive(string); // '1', ok -// type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok - -// // explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -// type genericIsPrimitive = () => IsPrimitive(T); -// type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -// type regexpIsPrimitive2 = genericIsPrimitive<>(); -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// // alternative, pass as parameters -// type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -// type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok -// type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// // FAILS!, '1' instead of '0', should delay overload selection until type argument is known - -// type map = (fn: Fn, obj: O) => { [P in keyof O]: Fn(P) }; // Fn(O[P]) -// type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); - -// binary function composition, still fails -type Fn1 = (v: T[]) => { [k: string]: T }; -type Fn2 = (v: { [k: string]: T }) => ReadonlyArray; -// type Fn3 = (v: T) => Fn2(Fn1(T)); -// type Fn4 = Fn3(1); -type X = Fn2(Fn1(1)); + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } + +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); diff --git a/tests/cases/conformance/types/rest/objectRestNegative.ts b/tests/cases/conformance/types/rest/objectRestNegative.ts index 13d214e453de4..fd224dcb93080 100644 --- a/tests/cases/conformance/types/rest/objectRestNegative.ts +++ b/tests/cases/conformance/types/rest/objectRestNegative.ts @@ -14,5 +14,5 @@ function generic(t: T) { return rest; } -let rest: { b: string } +let rest: { b: string }; ({a, ...rest.b + rest.b} = o); diff --git a/tests/cases/fourslash/underscoreTypings02.ts b/tests/cases/fourslash/underscoreTypings02.ts index be7d20427e229..f1a44925a87df 100644 --- a/tests/cases/fourslash/underscoreTypings02.ts +++ b/tests/cases/fourslash/underscoreTypings02.ts @@ -20,4 +20,4 @@ //// } goTo.position(0); -verify.numberOfErrorsInCurrentFile(2); +verify.numberOfErrorsInCurrentFile(1); From 4b2e8a1eb9ad4feea7a34fcf2d6870e6c56720ee Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Thu, 7 Sep 2017 02:37:23 +0800 Subject: [PATCH 10/25] give type calls own type, fixes eager eval --- src/compiler/binder.ts | 1 + src/compiler/checker.ts | 240 ++++++++++++++++----- src/compiler/declarationEmitter.ts | 14 ++ src/compiler/emitter.ts | 4 +- src/compiler/symbolWalker.ts | 11 +- src/compiler/transformers/ts.ts | 2 + src/compiler/types.ts | 30 ++- src/compiler/utilities.ts | 4 + tests/baselines/reference/typeCall.js | 30 +-- tests/baselines/reference/typeCall.symbols | 22 +- tests/baselines/reference/typeCall.types | 80 +++---- tests/cases/compiler/typeCall.ts | 18 +- 12 files changed, 310 insertions(+), 146 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a7e94da09d995..e38d91445d517 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3366,6 +3366,7 @@ namespace ts { case SyntaxKind.ThisType: case SyntaxKind.TypeOperator: case SyntaxKind.IndexedAccessType: + case SyntaxKind.TypeCall: case SyntaxKind.MappedType: case SyntaxKind.LiteralType: case SyntaxKind.NamespaceExportDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e366f322e7ea4..706ff8600fb5f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2537,6 +2537,12 @@ namespace ts { const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } + if (type.flags & TypeFlags.TypeCall) { + const fnNode = typeToTypeNodeHelper((type).function, context); + const argNodes = mapToTypeNodes((type).arguments, context); + const typeArgNodes = mapToTypeNodes((type).typeArguments, context); + return createTypeCall(fnNode, typeArgNodes, argNodes); + } Debug.fail("Should be unreachable."); @@ -3306,6 +3312,17 @@ namespace ts { writeType((type).indexType, TypeFormatFlags.None); writePunctuation(writer, SyntaxKind.CloseBracketToken); } + else if (type.flags & TypeFlags.TypeCall) { + writeType((type).function, TypeFormatFlags.None); + if ((type).typeArguments && (type).typeArguments.length) { + writePunctuation(writer, SyntaxKind.LessThanToken); + writeTypeList((type).typeArguments, SyntaxKind.CommaToken); + writePunctuation(writer, SyntaxKind.GreaterThanToken); + } + writePunctuation(writer, SyntaxKind.OpenParenToken); + writeTypeList((type).arguments, SyntaxKind.CommaToken); + writePunctuation(writer, SyntaxKind.CloseParenToken); + } else { // Should never get here // { ... } @@ -5912,10 +5929,19 @@ namespace ts { } } - function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type { + function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType | TypeCallType): Type { return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type) : type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type) : - getBaseConstraintOfType(type); + type.flags & TypeFlags.TypeCall ? getConstraintOfTypeCall(type) : + getBaseConstraintOfType(type); + } + + function getConstraintOfTypeCall(type: TypeCallType): Type { + const fn = type.function; + const typeArgs = map(type.typeArguments, getConstraintOfType); + const args = map(type.arguments, getConstraintOfType); + const call = createTypeCallType(fn, typeArgs, args); + return getTypeFromTypeCall(call); } function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type { @@ -7505,7 +7531,7 @@ namespace ts { return links.resolvedType; } - function getIndexTypeForGenericType(type: TypeVariable | UnionOrIntersectionType) { + function getIndexTypeForGenericType(type: TypeVariable | UnionOrIntersectionType | TypeCallType) { if (!type.resolvedIndexType) { type.resolvedIndexType = createType(TypeFlags.Index); type.resolvedIndexType.type = type; @@ -7524,7 +7550,7 @@ namespace ts { } function getIndexType(type: Type): Type { - return maybeTypeOfKind(type, TypeFlags.TypeVariable) ? getIndexTypeForGenericType(type) : + return maybeTypeOfKind(type, TypeFlags.TypeVariable) || isGenericTypeCallType(type) ? getIndexTypeForGenericType(type) : getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(type) : type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromPropertyNames(type); @@ -7543,26 +7569,88 @@ namespace ts { return links.resolvedType; } - function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { - const fn = typeNodeToExpression(node.type); - const args = map(node.arguments, typeNodeToExpression); - const callExpr = createCall(fn, node.typeArguments || [], args); - callExpr.parent = node; - callExpr.expression.parent = callExpr; - callExpr.expression.parent = callExpr.expression; - forEach(callExpr.arguments, (arg: Node) => { - arg.parent = callExpr; - (arg as ParenthesizedExpression).expression.parent = arg; - }); - forEach(callExpr.typeArguments, (arg: Node) => { - arg.parent = callExpr; - }); - return checkCallExpression(callExpr); + function isGenericTypeCallType(type: Type): boolean { + return type.flags & TypeFlags.TypeVariable ? true : + type.flags & TypeFlags.UnionOrIntersection ? forEach((type).types, isGenericTypeCallType) : + false; + } + + function createTypeCallType(fn: Type, typeArgs: Type[], args: Type[]): TypeCallType { + const type = createType(TypeFlags.TypeCall); + type.function = fn; + type.typeArguments = typeArgs; + type.arguments = args; + return type; + } + + // overlap with typeToTypeNode? + function createTypeCallNodeFromType(type: TypeCallType): TypeCallTypeNode { + const node = createNodeBuilder().typeToTypeNode(type); + fixupParentReferences(node); + return node; + } + + function getTypeCallType(fn: Type, typeArgs: Type[], args: Type[], node?: TypeCallTypeNode): Type { + const type = createTypeCallType(fn, typeArgs, args); + if (isGenericTypeCallType(fn) || some(typeArgs, isGenericTypeCallType) || some(args, isGenericTypeCallType)) { + return type; + } + return getTypeFromTypeCall(type, node); + } + + function getTypeFromTypeCall(type: TypeCallType, node = createTypeCallNodeFromType(type)): Type { + const fn = type.function; + const typeArgs = type.typeArguments; + const args = type.arguments; + const calls = getSignaturesOfType(fn, SignatureKind.Call); + const sig = resolveCall(node, calls, []); + if (!sig.typeParameters || !sig.typeParameters.length) { + return getReturnTypeOfSignature(sig); + } + let signature: Signature; + if (typeArgs && typeArgs.length) { + signature = getSignatureInstantiation(sig, typeArgs); + } + else { + const inferenceContext = createInferenceContext(sig, InferenceFlags.InferUnionTypes); + const types = inferTypeArgumentsForTypeCall(sig, args, inferenceContext); // TODO: add Fn(this: A, B, C) syntax + signature = getSignatureInstantiation(sig, types); + } + return getReturnTypeOfSignature(signature); + } + + function inferTypeArgumentsForTypeCall(signature: Signature, args: Type[], context: InferenceContext, thisArgumentType?: Type): Type[] { + const thisType = getThisTypeOfSignature(signature); + if (thisType) { + inferTypes(context.inferences || [], thisArgumentType, thisType); + } + const argCount = args.length; + for (let i = 0; i < argCount; i++) { + const paramType = getTypeAtPosition(signature, i); + const argType = args[i]; + inferTypes(context.inferences || [], argType, paramType); + } + return getInferredTypes(context); + } + + function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getTypeCallType( + getTypeFromTypeNode(node.type), + map(node.typeArguments, getTypeFromTypeNode), + map(node.arguments, getTypeFromTypeNode), + node + ); + } + return links.resolvedType; } // null! as type function typeNodeToExpression(type: TypeNode): Expression { - return createAsExpression(createNonNullExpression(createNull()), type); + const expr = createAsExpression(createNonNullExpression(createNull()), type); + expr.parent = type.parent; + return expr; } function createIndexedAccessType(objectType: Type, indexType: Type) { @@ -7572,28 +7660,21 @@ namespace ts { return type; } - // // Parser.fixupParentReferences - // function fixupParentReferences(rootNode: Node) { - // let parent: Node = rootNode; - // forEachChild(rootNode, visitNode); - // return; - // function visitNode(n: Node): void { - // if (n.parent !== parent) { - // n.parent = parent; - // const saveParent = parent; - // parent = n; - // forEachChild(n, visitNode); - // if (n.jsDoc) { - // for (const jsDoc of n.jsDoc) { - // jsDoc.parent = n; - // parent = jsDoc; - // forEachChild(jsDoc, visitNode); - // } - // } - // parent = saveParent; - // } - // } - // } + // Parser.fixupParentReferences + function fixupParentReferences(rootNode: Node) { + let parent: Node = rootNode; + forEachChild(rootNode, visitNode); + return; + function visitNode(n: Node): void { + if (n.parent !== parent) { + n.parent = parent; + const saveParent = parent; + parent = n; + forEachChild(n, visitNode); + parent = saveParent; + } + } + } function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; @@ -8253,7 +8334,7 @@ namespace ts { } function isMappableType(type: Type) { - return type.flags & (TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess); + return type.flags & (TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess | TypeFlags.TypeCall); } function instantiateMappedObjectType(type: MappedType, mapper: TypeMapper): Type { @@ -8401,6 +8482,13 @@ namespace ts { if (type.flags & TypeFlags.IndexedAccess) { return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); } + if (type.flags & TypeFlags.TypeCall) { + return getTypeCallType( + instantiateType((type).function, mapper), + (type).typeArguments, + (type).arguments + ); + } return type; } @@ -9355,6 +9443,15 @@ namespace ts { } } } + else if (target.flags & TypeFlags.TypeCall) { + const constraint = getConstraintOfTypeCall(target); + if (constraint) { + if (result = isRelatedTo(source, constraint, reportErrors)) { + errorInfo = saveErrorInfo; + return result; + } + } + } if (source.flags & TypeFlags.TypeParameter) { // A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X. @@ -9402,6 +9499,15 @@ namespace ts { } } } + else if (source.flags & TypeFlags.TypeCall) { + const constraint = getConstraintOfTypeCall(source); + if (constraint) { + if (result = isRelatedTo(source, constraint, reportErrors)) { + errorInfo = saveErrorInfo; + return result; + } + } + } else { if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { // We have type references to same target type, see if relationship holds for all type arguments @@ -15054,12 +15160,12 @@ namespace ts { return true; } - function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression { + function callLikeExpressionMayHaveTypeArguments(node: CallLike): node is CallExpression | NewExpression { // TODO: Also include tagged templates (https://github.com/Microsoft/TypeScript/issues/11947) return isCallOrNewExpression(node); } - function resolveUntypedCall(node: CallLikeExpression): Signature { + function resolveUntypedCall(node: CallLike): Signature { if (callLikeExpressionMayHaveTypeArguments(node)) { // Check type arguments even though we will give an error that untyped calls may not accept type arguments. // This gets us diagnostics for the type arguments and marks them as referenced. @@ -15077,7 +15183,7 @@ namespace ts { return anySignature; } - function resolveErrorCall(node: CallLikeExpression): Signature { + function resolveErrorCall(node: CallLike): Signature { resolveUntypedCall(node); return unknownSignature; } @@ -15146,7 +15252,7 @@ namespace ts { return -1; } - function hasCorrectArity(node: CallLikeExpression, args: ReadonlyArray, signature: Signature, signatureHelpTrailingComma = false) { + function hasCorrectArity(node: CallLike, args: ReadonlyArray, signature: Signature, signatureHelpTrailingComma = false) { let argCount: number; // Apparent number of arguments we will have in this call let typeArguments: NodeArray; // Type arguments (undefined if none) let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments @@ -15257,7 +15363,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, excludeArgument: boolean[], context: InferenceContext): Type[] { + function inferTypeArguments(node: CallLike, signature: Signature, args: ReadonlyArray, excludeArgument: boolean[], context: InferenceContext): Type[] { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (const inference of context.inferences) { // As an optimization, we don't have to clear (and later recompute) inferred types @@ -15273,7 +15379,7 @@ namespace ts { // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the // return type of 'wrap'. - if (node.kind !== SyntaxKind.Decorator) { + if (node.kind !== SyntaxKind.Decorator && node.kind !== SyntaxKind.TypeCall) { const contextualType = getContextualType(node); if (contextualType) { // We clone the contextual mapper to avoid disturbing a resolution in progress for an @@ -15410,7 +15516,7 @@ namespace ts { } function checkApplicableSignature( - node: CallLikeExpression, + node: CallLike, args: ReadonlyArray, signature: Signature, relation: Map, @@ -15462,7 +15568,7 @@ namespace ts { /** * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. */ - function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression { + function getThisArgumentOfCall(node: CallLike): LeftHandSideExpression { if (node.kind === SyntaxKind.CallExpression) { const callee = (node).expression; if (callee.kind === SyntaxKind.PropertyAccessExpression) { @@ -15483,7 +15589,7 @@ namespace ts { * If 'node' is a Decorator, the argument list will be `undefined`, and its arguments and types * will be supplied from calls to `getEffectiveArgumentCount` and `getEffectiveArgumentType`. */ - function getEffectiveCallArguments(node: CallLikeExpression): ReadonlyArray { + function getEffectiveCallArguments(node: CallLike): ReadonlyArray { if (node.kind === SyntaxKind.TaggedTemplateExpression) { const template = (node).template; const args: Expression[] = [undefined]; @@ -15503,6 +15609,9 @@ namespace ts { else if (isJsxOpeningLikeElement(node)) { return node.attributes.properties.length > 0 ? [node.attributes] : emptyArray; } + else if (isTypeCallTypeNode(node)) { + return map(>node.arguments, (arg: TypeNode) => typeNodeToExpression(arg)) || emptyArray; + } else { return node.arguments || emptyArray; } @@ -15522,7 +15631,7 @@ namespace ts { * us to match a property decorator. * Otherwise, the argument count is the length of the 'args' array. */ - function getEffectiveArgumentCount(node: CallLikeExpression, args: ReadonlyArray, signature: Signature) { + function getEffectiveArgumentCount(node: CallLike, args: ReadonlyArray, signature: Signature) { if (node.kind === SyntaxKind.Decorator) { switch (node.parent.kind) { case SyntaxKind.ClassDeclaration: @@ -15735,7 +15844,7 @@ namespace ts { /** * Gets the effective argument type for an argument in a call expression. */ - function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number): Type { + function getEffectiveArgumentType(node: CallLike, argIndex: number): Type { // Decorators provide special arguments, a tagged template expression provides // a special first argument, and string literals get string literal types // unless we're reporting errors @@ -15745,6 +15854,9 @@ namespace ts { else if (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression) { return getGlobalTemplateStringsArrayType(); } + else if (node.kind === SyntaxKind.TypeCall) { + return getTypeFromTypeNode((node).arguments[argIndex]); + } // This is not a synthetic argument, so we return 'undefined' // to signal that the caller needs to check the argument. @@ -15754,7 +15866,7 @@ namespace ts { /** * Gets the effective argument expression for an argument in a call expression. */ - function getEffectiveArgument(node: CallLikeExpression, args: ReadonlyArray, argIndex: number) { + function getEffectiveArgument(node: CallLike, args: ReadonlyArray, argIndex: number) { // For a decorator or the first argument of a tagged template expression we return undefined. if (node.kind === SyntaxKind.Decorator || (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression)) { @@ -15767,7 +15879,7 @@ namespace ts { /** * Gets the error node to use when reporting errors for an effective argument. */ - function getEffectiveArgumentErrorNode(node: CallLikeExpression, argIndex: number, arg: Expression) { + function getEffectiveArgumentErrorNode(node: CallLike, argIndex: number, arg: Expression) { if (node.kind === SyntaxKind.Decorator) { // For a decorator, we use the expression of the decorator for error reporting. return (node).expression; @@ -15781,7 +15893,7 @@ namespace ts { } } - function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage): Signature { + function resolveCall(node: CallLike, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage): Signature { const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; const isDecorator = node.kind === SyntaxKind.Decorator; const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); @@ -15792,7 +15904,7 @@ namespace ts { typeArguments = (node).typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if ((node).expression.kind !== SyntaxKind.SuperKeyword) { + if (!isTypeCallTypeNode(node) && (node).expression.kind !== SyntaxKind.SuperKeyword) { forEach(typeArguments, checkSourceElement); } } @@ -22514,7 +22626,17 @@ namespace ts { checkSourceElement(node.type); forEach(node.arguments, checkSourceElement); forEach(node.typeArguments, checkSourceElement); - getTypeFromTypeCallNode(node); // construct node and check it (checkCallExpression) + const callExpr = getCallExpressionFromTypeCallNode(node); + checkCallExpression(callExpr); + } + + function getCallExpressionFromTypeCallNode(node: TypeCallTypeNode): CallExpression { + const fn = typeNodeToExpression(node.type); + const args = map(node.arguments, typeNodeToExpression); + const callExpr = createCall(fn, node.typeArguments, args); + fixupParentReferences(callExpr); + callExpr.parent = node; + return callExpr; } // Function and class expression bodies are checked after all statements in the enclosing body. This is diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 3de2091502949..6c109628b1419 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -445,6 +445,8 @@ namespace ts { return emitTypeOperator(type); case SyntaxKind.IndexedAccessType: return emitIndexedAccessType(type); + case SyntaxKind.TypeCall: + return emitTypeCall(type); case SyntaxKind.MappedType: return emitMappedType(type); case SyntaxKind.FunctionType: @@ -553,6 +555,18 @@ namespace ts { write("]"); } + function emitTypeCall(node: TypeCallTypeNode) { + emitType(node.type); + if (node.typeArguments && node.typeArguments.length) { + write("<"); + emitCommaList(node.typeArguments, emitType); + write(">"); + } + write("("); + emitCommaList(node.arguments, emitType); + write(")"); + } + function emitMappedType(node: MappedTypeNode) { const prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 641f4dbc833d3..ad2c85d8553a3 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -559,6 +559,8 @@ namespace ts { return emitMappedType(node); case SyntaxKind.LiteralType: return emitLiteralType(node); + case SyntaxKind.TypeCall: + return emitTypeCall(node); // Binding patterns case SyntaxKind.ObjectBindingPattern: @@ -753,8 +755,6 @@ namespace ts { return emitPropertyAccessExpression(node); case SyntaxKind.ElementAccessExpression: return emitElementAccessExpression(node); - case SyntaxKind.TypeCall: - return emitTypeCall(node); case SyntaxKind.CallExpression: return emitCallExpression(node); case SyntaxKind.NewExpression: diff --git a/src/compiler/symbolWalker.ts b/src/compiler/symbolWalker.ts index e20ef9f9d9877..b8828424adbfd 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -77,6 +77,9 @@ namespace ts { if (type.flags & TypeFlags.IndexedAccess) { visitIndexedAccessType(type as IndexedAccessType); } + if (type.flags & TypeFlags.TypeCall) { + visitTypeCallType(type as TypeCallType); + } } function visitTypeList(types: Type[]): void { @@ -111,6 +114,12 @@ namespace ts { visitType(type.constraint); } + function visitTypeCallType(type: TypeCallType): void { + visitType(type.function); + visitTypeList(type.typeArguments); + visitTypeList(type.arguments); + } + function visitMappedType(type: MappedType): void { visitType(type.typeParameter); visitType(type.constraintType); @@ -188,4 +197,4 @@ namespace ts { } } } -} \ No newline at end of file +} diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 692c758bc7504..8739ff56db90c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -359,6 +359,7 @@ namespace ts { case SyntaxKind.IndexedAccessType: case SyntaxKind.MappedType: case SyntaxKind.LiteralType: + case SyntaxKind.TypeCall: // TypeScript type nodes are elided. case SyntaxKind.IndexSignature: @@ -1833,6 +1834,7 @@ namespace ts { case SyntaxKind.TypeQuery: case SyntaxKind.TypeOperator: case SyntaxKind.IndexedAccessType: + case SyntaxKind.TypeCall: case SyntaxKind.MappedType: case SyntaxKind.TypeLiteral: case SyntaxKind.AnyKeyword: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9df0ba513e81d..9c333c7122888 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1534,6 +1534,8 @@ namespace ts { export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; + export type CallLike = CallLikeExpression | TypeCallTypeNode; + export interface AsExpression extends Expression { kind: SyntaxKind.AsExpression; expression: Expression; @@ -3149,17 +3151,18 @@ namespace ts { Intersection = 1 << 17, // Intersection (T & U) Index = 1 << 18, // keyof T IndexedAccess = 1 << 19, // T[K] + TypeCall = 1 << 20, // F(T) /* @internal */ - FreshLiteral = 1 << 20, // Fresh literal type + FreshLiteral = 1 << 21, // Fresh literal type /* @internal */ - ContainsWideningType = 1 << 21, // Type is or contains undefined or null widening type + ContainsWideningType = 1 << 22, // Type is or contains undefined or null widening type /* @internal */ - ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type + ContainsObjectLiteral = 1 << 23, // Type is or contains object literal type /* @internal */ - ContainsAnyFunctionType = 1 << 23, // Type is or contains the anyFunctionType - NonPrimitive = 1 << 24, // intrinsic object type + ContainsAnyFunctionType = 1 << 24, // Type is or contains the anyFunctionType + NonPrimitive = 1 << 25, // intrinsic object type /* @internal */ - JsxAttributes = 1 << 25, // Jsx attributes type + JsxAttributes = 1 << 26, // Jsx attributes type /* @internal */ Nullable = Undefined | Null, @@ -3178,12 +3181,12 @@ namespace ts { EnumLike = Enum | EnumLiteral, UnionOrIntersection = Union | Intersection, StructuredType = Object | Union | Intersection, - StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess, - TypeVariable = TypeParameter | IndexedAccess, + StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess | TypeCall, + TypeVariable = TypeParameter | IndexedAccess | TypeCall, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never - Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive, + Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | TypeCall | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive, NotUnionOrUnit = Any | ESSymbol | Object | NonPrimitive, /* @internal */ RequiresWidening = ContainsWideningType | ContainsObjectLiteral, @@ -3408,6 +3411,15 @@ namespace ts { constraint?: Type; } + // F(T) types (TypeFlags.TypeCall) + export interface TypeCallType extends TypeVariable { + function: Type; + typeArguments: Type[]; + arguments: Type[]; + /* @internal */ + resolvedIndexType: IndexType; + } + // keyof T types (TypeFlags.Index) export interface IndexType extends Type { type: TypeVariable | UnionOrIntersectionType; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7047a11a9bdb9..a69de01016095 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4132,6 +4132,10 @@ namespace ts { return node.kind === SyntaxKind.IndexedAccessType; } + export function isTypeCallTypeNode(node: Node): node is TypeCallTypeNode { + return node.kind === SyntaxKind.TypeCall; + } + export function isMappedTypeNode(node: Node): node is MappedTypeNode { return node.kind === SyntaxKind.MappedType; } diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 8f8225d218290..e083dbf872ee4 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -68,9 +68,9 @@ type Fn3 = (v3: T3) => Fn2(Fn1(T3)); // type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; type Fn4b = Fn3(typeof ones); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. type Fn4c = Fn3(1[]); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); @@ -101,11 +101,11 @@ type Obj = { } type T1 = (() => number)(); -type T7 = CallMember; // fails, got any, want number -type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number +type T7 = CallMember; +type T8 = IndexCall<() => Obj, 'x'>; type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } type T13 = keyof (() => Obj)(); -type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' +type T14 = KeyOfCall<() => Obj>; type T15 = Obj['z']()['kind']; type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } @@ -113,14 +113,14 @@ type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: let a1: () => string; let b1: typeof a1(); -type Assert any> = T(); // fails, eagerly resolved to any -let c1: Assert; // fails, got any, want string +type Assert any> = T(); +let c1: Assert; -declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any -infer1(null! as () => number); // fails, got any, want number +declare function infer1 any>(x: T): T(); +infer1(null! as () => number); -declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any -infer2(null! as { a: () => number }); // fails, got any, want number +declare function infer2 any>(x: { a: T }): T(); +infer2(null! as { a: () => number }); declare function infer3(x: { a: () => T }): T; infer3(null! as { a: () => number }); @@ -171,15 +171,15 @@ var fn1 = null; var fn2 = null; // type Fn4 = Fn3(1); // errors, ok var ones = null; -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok var y = fn2(fn1(ones)); var a1; var b1; -var c1; // fails, got any, want string -infer1(null); // fails, got any, want number -infer2(null); // fails, got any, want number +var c1; +infer1(null); +infer2(null); infer3(null); var res3 = infer3(null); infer4(5, function () { return 5; }); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index ae3d6a2e1b6bb..336a6e2790af1 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -228,12 +228,12 @@ type Fn4b = Fn3(typeof ones); >Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) >ones : Symbol(ones, Decl(typeCall.ts, 67, 3)) -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. type Fn4c = Fn3(1[]); >Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 68, 29)) >Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); @@ -348,12 +348,12 @@ type Obj = { type T1 = (() => number)(); >T1 : Symbol(T1, Decl(typeCall.ts, 99, 1)) -type T7 = CallMember; // fails, got any, want number +type T7 = CallMember; >T7 : Symbol(T7, Decl(typeCall.ts, 101, 27)) >CallMember : Symbol(CallMember, Decl(typeCall.ts, 77, 85)) >Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) -type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number +type T8 = IndexCall<() => Obj, 'x'>; >T8 : Symbol(T8, Decl(typeCall.ts, 102, 31)) >IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 75, 23)) >Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) @@ -367,7 +367,7 @@ type T13 = keyof (() => Obj)(); >T13 : Symbol(T13, Decl(typeCall.ts, 104, 32)) >Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) -type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' +type T14 = KeyOfCall<() => Obj>; >T14 : Symbol(T14, Decl(typeCall.ts, 105, 31)) >KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 89, 2)) >Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) @@ -398,27 +398,27 @@ let b1: typeof a1(); >b1 : Symbol(b1, Decl(typeCall.ts, 113, 3)) >a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) -type Assert any> = T(); // fails, eagerly resolved to any +type Assert any> = T(); >Assert : Symbol(Assert, Decl(typeCall.ts, 113, 20)) >T : Symbol(T, Decl(typeCall.ts, 114, 12)) >T : Symbol(T, Decl(typeCall.ts, 114, 12)) -let c1: Assert; // fails, got any, want string +let c1: Assert; >c1 : Symbol(c1, Decl(typeCall.ts, 115, 3)) >Assert : Symbol(Assert, Decl(typeCall.ts, 113, 20)) >a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) -declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any +declare function infer1 any>(x: T): T(); >infer1 : Symbol(infer1, Decl(typeCall.ts, 115, 26)) >T : Symbol(T, Decl(typeCall.ts, 117, 24)) >x : Symbol(x, Decl(typeCall.ts, 117, 45)) >T : Symbol(T, Decl(typeCall.ts, 117, 24)) >T : Symbol(T, Decl(typeCall.ts, 117, 24)) -infer1(null! as () => number); // fails, got any, want number +infer1(null! as () => number); >infer1 : Symbol(infer1, Decl(typeCall.ts, 115, 26)) -declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any +declare function infer2 any>(x: { a: T }): T(); >infer2 : Symbol(infer2, Decl(typeCall.ts, 118, 30)) >T : Symbol(T, Decl(typeCall.ts, 120, 24)) >x : Symbol(x, Decl(typeCall.ts, 120, 45)) @@ -426,7 +426,7 @@ declare function infer2 any>(x: { a: T }): T(); // fails, eagerl >T : Symbol(T, Decl(typeCall.ts, 120, 24)) >T : Symbol(T, Decl(typeCall.ts, 120, 24)) -infer2(null! as { a: () => number }); // fails, got any, want number +infer2(null! as { a: () => number }); >infer2 : Symbol(infer2, Decl(typeCall.ts, 118, 30)) >a : Symbol(a, Decl(typeCall.ts, 121, 17)) diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index b547326ef8c9e..d9b89dca990f1 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -64,14 +64,14 @@ type h = Id(123); >Id : Id type Wrap = Id(T); ->Wrap : T +>Wrap : Id(T) >T : T >Id : Id >T : T type i = Wrap<123>; ->i : 123 ->Wrap : T +>i : Id(T) +>Wrap : Id(T) type F5 = () => () => { a: () => 1; }; >F5 : F5 @@ -126,11 +126,11 @@ type genericIsPrimitive = () => IsPrimitive(T); >T : T type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok ->stringIsPrimitive2 : "1" +>stringIsPrimitive2 : IsPrimitive(T) >genericIsPrimitive : genericIsPrimitive type regexpIsPrimitive2 = genericIsPrimitive<>(); ->regexpIsPrimitive2 : "1" +>regexpIsPrimitive2 : IsPrimitive(T) >genericIsPrimitive : genericIsPrimitive // fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known @@ -145,11 +145,11 @@ type genericIsPrimitive3 = (v: T) => IsPrimitive(T); >T : T type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok ->stringIsPrimitive3 : "1" +>stringIsPrimitive3 : IsPrimitive(T) >genericIsPrimitive3 : genericIsPrimitive3 type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) ->regexpIsPrimitive3 : "1" +>regexpIsPrimitive3 : IsPrimitive(T) >genericIsPrimitive3 : genericIsPrimitive3 >RegExp : RegExp @@ -175,7 +175,7 @@ type map = any, O extends { [k: string]: T }, T>(fn: Fn, o >P : P type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : { a: any; b: any; c: any; } +>z : { a: ((v: T) => [T])(O[P]); b: ((v: T) => [T])(O[P]); c: ((v: T) => [T])(O[P]); } >map : map >T : T >v : T @@ -236,16 +236,16 @@ let ones = null! as 1[]; >null : null type Fn4b = Fn3(typeof ones); ->Fn4b : ReadonlyArray +>Fn4b : Fn2(Fn1(T3)) >Fn3 : Fn3 >ones : 1[] -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. type Fn4c = Fn3(1[]); ->Fn4c : ReadonlyArray +>Fn4c : Fn2(Fn1(T3)) >Fn3 : Fn3 -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); @@ -262,7 +262,7 @@ type Y = Fn2(Fn1(1[])); >Fn1 : Fn1 type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : { [k: string]: any; }[K] +>IndexCall : T()[K] >T : T >k : string >K : K @@ -271,7 +271,7 @@ type IndexCall { [k: string]: any }, K extends keyof (T())> = T( >K : K type CallMember any }, K extends keyof T> = T[K](); ->CallMember : any +>CallMember : T[K]() >T : T >k : string >K : K @@ -304,7 +304,7 @@ type HasKey = ( >Key : Key type HasKindKey any> = HasKey; ->HasKindKey : any +>HasKindKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["kind"] >T : T >HasKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })[Key] >T : T @@ -326,7 +326,7 @@ type MapHasKey any }, Key extends string> = { }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : string +>KeyOfCall : keyof T() >T : T >T : T @@ -362,14 +362,14 @@ type Obj = { type T1 = (() => number)(); >T1 : number -type T7 = CallMember; // fails, got any, want number ->T7 : any ->CallMember : any +type T7 = CallMember; +>T7 : number +>CallMember : T[K]() >Obj : Obj -type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number ->T8 : any ->IndexCall : { [k: string]: any; }[K] +type T8 = IndexCall<() => Obj, 'x'>; +>T8 : () => number +>IndexCall : T()[K] >Obj : Obj type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } @@ -381,9 +381,9 @@ type T13 = keyof (() => Obj)(); >T13 : "x" | "z" >Obj : Obj -type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' ->T14 : string ->KeyOfCall : string +type T14 = KeyOfCall<() => Obj>; +>T14 : "x" | "z" +>KeyOfCall : keyof T() >Obj : Obj type T15 = Obj['z']()['kind']; @@ -412,41 +412,41 @@ let b1: typeof a1(); >b1 : string >a1 : () => string -type Assert any> = T(); // fails, eagerly resolved to any ->Assert : any +type Assert any> = T(); +>Assert : T() >T : T >T : T -let c1: Assert; // fails, got any, want string ->c1 : any ->Assert : any +let c1: Assert; +>c1 : string +>Assert : T() >a1 : () => string -declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any ->infer1 : any>(x: T) => any +declare function infer1 any>(x: T): T(); +>infer1 : any>(x: T) => T() >T : T >x : T >T : T >T : T -infer1(null! as () => number); // fails, got any, want number ->infer1(null! as () => number) : any ->infer1 : any>(x: T) => any +infer1(null! as () => number); +>infer1(null! as () => number) : number +>infer1 : any>(x: T) => T() >null! as () => number : () => number >null! : never >null : null -declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any ->infer2 : any>(x: { a: T; }) => any +declare function infer2 any>(x: { a: T }): T(); +>infer2 : any>(x: { a: T; }) => T() >T : T >x : { a: T; } >a : T >T : T >T : T -infer2(null! as { a: () => number }); // fails, got any, want number ->infer2(null! as { a: () => number }) : any ->infer2 : any>(x: { a: T; }) => any +infer2(null! as { a: () => number }); +>infer2(null! as { a: () => number }) : number +>infer2 : any>(x: { a: T; }) => T() >null! as { a: () => number } : { a: () => number; } >null! : never >null : null diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 9c18d5cab209c..7c045cffed38f 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -104,11 +104,11 @@ type Obj = { } type T1 = (() => number)(); -type T7 = CallMember; // fails, got any, want number -type T8 = IndexCall<() => Obj, 'x'>; // fails, got any, want () => number +type T7 = CallMember; +type T8 = IndexCall<() => Obj, 'x'>; type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } type T13 = keyof (() => Obj)(); -type T14 = KeyOfCall<() => Obj>; // fails, got string, want 'x' | 'y' +type T14 = KeyOfCall<() => Obj>; type T15 = Obj['z']()['kind']; type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } @@ -116,14 +116,14 @@ type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: let a1: () => string; let b1: typeof a1(); -type Assert any> = T(); // fails, eagerly resolved to any -let c1: Assert; // fails, got any, want string +type Assert any> = T(); +let c1: Assert; -declare function infer1 any>(x: T): T(); // fails, eagerly resolved to any -infer1(null! as () => number); // fails, got any, want number +declare function infer1 any>(x: T): T(); +infer1(null! as () => number); -declare function infer2 any>(x: { a: T }): T(); // fails, eagerly resolved to any -infer2(null! as { a: () => number }); // fails, got any, want number +declare function infer2 any>(x: { a: T }): T(); +infer2(null! as { a: () => number }); declare function infer3(x: { a: () => T }): T; infer3(null! as { a: () => number }); From 2f2e8005c56ca7dd69e2cfa93249a7bccba3818a Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sat, 9 Sep 2017 01:51:56 +0800 Subject: [PATCH 11/25] fix other tests --- src/compiler/checker.ts | 33 ++----------------- src/compiler/parser.ts | 3 ++ .../reference/arrayTypeOfTypeOf.errors.txt | 16 --------- .../reference/arrayTypeOfTypeOf.symbols | 22 +++++++++++++ .../reference/arrayTypeOfTypeOf.types | 23 +++++++++++++ .../reference/invalidTypeOfTarget.errors.txt | 5 ++- .../reference/overloadSelection.types | 2 +- .../reference/parserObjectType5.errors.txt | 5 +-- .../reference/parserTypeQuery8.errors.txt | 7 ++-- 9 files changed, 58 insertions(+), 58 deletions(-) delete mode 100644 tests/baselines/reference/arrayTypeOfTypeOf.errors.txt create mode 100644 tests/baselines/reference/arrayTypeOfTypeOf.symbols create mode 100644 tests/baselines/reference/arrayTypeOfTypeOf.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 706ff8600fb5f..55e9fdc40ef62 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7586,7 +7586,6 @@ namespace ts { // overlap with typeToTypeNode? function createTypeCallNodeFromType(type: TypeCallType): TypeCallTypeNode { const node = createNodeBuilder().typeToTypeNode(type); - fixupParentReferences(node); return node; } @@ -7648,9 +7647,7 @@ namespace ts { // null! as type function typeNodeToExpression(type: TypeNode): Expression { - const expr = createAsExpression(createNonNullExpression(createNull()), type); - expr.parent = type.parent; - return expr; + return createAsExpression(createNonNullExpression(createNull()), type); } function createIndexedAccessType(objectType: Type, indexType: Type) { @@ -7660,22 +7657,6 @@ namespace ts { return type; } - // Parser.fixupParentReferences - function fixupParentReferences(rootNode: Node) { - let parent: Node = rootNode; - forEachChild(rootNode, visitNode); - return; - function visitNode(n: Node): void { - if (n.parent !== parent) { - n.parent = parent; - const saveParent = parent; - parent = n; - forEachChild(n, visitNode); - parent = saveParent; - } - } - } - function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = indexType.flags & TypeFlags.StringOrNumberLiteral ? @@ -22626,17 +22607,7 @@ namespace ts { checkSourceElement(node.type); forEach(node.arguments, checkSourceElement); forEach(node.typeArguments, checkSourceElement); - const callExpr = getCallExpressionFromTypeCallNode(node); - checkCallExpression(callExpr); - } - - function getCallExpressionFromTypeCallNode(node: TypeCallTypeNode): CallExpression { - const fn = typeNodeToExpression(node.type); - const args = map(node.arguments, typeNodeToExpression); - const callExpr = createCall(fn, node.typeArguments, args); - fixupParentReferences(callExpr); - callExpr.parent = node; - return callExpr; + getTypeFromTypeCallNode(node); } // Function and class expression bodies are checked after all statements in the enclosing body. This is diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6338708e47da6..c8c3ea934e340 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4293,6 +4293,9 @@ namespace ts { return undefined; } + if (token() !== SyntaxKind.OpenParenToken) { + return; + } const args = parseTypeArgumentList(); const callExpr = createNode(SyntaxKind.TypeCall, type.pos); callExpr.type = type; diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt b/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt deleted file mode 100644 index 3479bd8044388..0000000000000 --- a/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt +++ /dev/null @@ -1,16 +0,0 @@ -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,30): error TS1005: '(' expected. -tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,32): error TS1005: '(' expected. - - -==== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts (2 errors) ==== - // array type cannot use typeof. - - var x = 1; - var xs: typeof x[]; // Not an error. This is equivalent to Array - var xs2: typeof Array; - var xs3: typeof Array; - ~ -!!! error TS1005: '(' expected. - var xs4: typeof Array; - ~ -!!! error TS1005: '(' expected. \ No newline at end of file diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.symbols b/tests/baselines/reference/arrayTypeOfTypeOf.symbols new file mode 100644 index 0000000000000..9c63f3ac21af4 --- /dev/null +++ b/tests/baselines/reference/arrayTypeOfTypeOf.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts === +// array type cannot use typeof. + +var x = 1; +>x : Symbol(x, Decl(arrayTypeOfTypeOf.ts, 2, 3)) + +var xs: typeof x[]; // Not an error. This is equivalent to Array +>xs : Symbol(xs, Decl(arrayTypeOfTypeOf.ts, 3, 3)) +>x : Symbol(x, Decl(arrayTypeOfTypeOf.ts, 2, 3)) + +var xs2: typeof Array; +>xs2 : Symbol(xs2, Decl(arrayTypeOfTypeOf.ts, 4, 3)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +var xs3: typeof Array; +>xs3 : Symbol(xs3, Decl(arrayTypeOfTypeOf.ts, 5, 3)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +var xs4: typeof Array; +>xs4 : Symbol(xs4, Decl(arrayTypeOfTypeOf.ts, 6, 3)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.types b/tests/baselines/reference/arrayTypeOfTypeOf.types new file mode 100644 index 0000000000000..bb5856e5c7e40 --- /dev/null +++ b/tests/baselines/reference/arrayTypeOfTypeOf.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts === +// array type cannot use typeof. + +var x = 1; +>x : number +>1 : 1 + +var xs: typeof x[]; // Not an error. This is equivalent to Array +>xs : number[] +>x : number + +var xs2: typeof Array; +>xs2 : ArrayConstructor +>Array : ArrayConstructor + +var xs3: typeof Array; +>xs3 : ArrayConstructor +>Array : ArrayConstructor + +var xs4: typeof Array; +>xs4 : ArrayConstructor +>Array : ArrayConstructor + diff --git a/tests/baselines/reference/invalidTypeOfTarget.errors.txt b/tests/baselines/reference/invalidTypeOfTarget.errors.txt index 569c36d1f8552..84a5b5adbd4eb 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.errors.txt +++ b/tests/baselines/reference/invalidTypeOfTarget.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(1,16): error TS1003: Identifier expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,9): error TS2346: Call target does not contain any signatures. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,18): error TS1005: ',' expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,20): error TS1134: Variable declaration expected. @@ -14,11 +15,13 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(8,16): error TS1003: Identifier expected. -==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (14 errors) ==== +==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (15 errors) ==== var x1: typeof {}; ~ !!! error TS1003: Identifier expected. var x2: typeof (): void; + ~~~~~~~~~ +!!! error TS2346: Call target does not contain any signatures. ~ !!! error TS1003: Identifier expected. ~ diff --git a/tests/baselines/reference/overloadSelection.types b/tests/baselines/reference/overloadSelection.types index 29bf2c3aa7a8d..997fd7ab9e044 100644 --- a/tests/baselines/reference/overloadSelection.types +++ b/tests/baselines/reference/overloadSelection.types @@ -18,7 +18,7 @@ type Wrap = (v: T) => Match(T); >T : T type A = Wrap(RegExp); ->A : 1 +>A : Match(T) >Wrap : Wrap >RegExp : RegExp diff --git a/tests/baselines/reference/parserObjectType5.errors.txt b/tests/baselines/reference/parserObjectType5.errors.txt index d4db1d2d85c51..9c74627f42cce 100644 --- a/tests/baselines/reference/parserObjectType5.errors.txt +++ b/tests/baselines/reference/parserObjectType5.errors.txt @@ -1,13 +1,10 @@ tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(2,7): error TS2304: Cannot find name 'B'. -tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,7): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (1 errors) ==== var v: { A: B ~ !!! error TS2304: Cannot find name 'B'. ; - ~ -!!! error TS1005: '(' expected. }; \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.errors.txt b/tests/baselines/reference/parserTypeQuery8.errors.txt index 2034bf9033647..ab24604ba90fa 100644 --- a/tests/baselines/reference/parserTypeQuery8.errors.txt +++ b/tests/baselines/reference/parserTypeQuery8.errors.txt @@ -1,10 +1,7 @@ tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,15): error TS2304: Cannot find name 'A'. -tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,19): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (1 errors) ==== var v: typeof A ~ -!!! error TS2304: Cannot find name 'A'. - -!!! error TS1005: '(' expected. \ No newline at end of file +!!! error TS2304: Cannot find name 'A'. \ No newline at end of file From c54eea7b86678650efae53871e3570ac5ac6f7ab Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sat, 9 Sep 2017 13:02:10 +0800 Subject: [PATCH 12/25] drop type arg support, works fine but not worth it --- src/compiler/checker.ts | 54 +- src/compiler/declarationEmitter.ts | 7 +- src/compiler/emitter.ts | 3 +- src/compiler/factory.ts | 12 +- src/compiler/parser.ts | 37 +- src/compiler/symbolWalker.ts | 1 - src/compiler/types.ts | 4 +- src/compiler/visitor.ts | 5 +- .../reference/arrayTypeOfTypeOf.errors.txt | 28 + .../baselines/reference/arrayTypeOfTypeOf.js | 4 +- .../emptyGenericParamList.errors.txt | 7 +- .../emptyTypeArgumentList.errors.txt | 8 + .../emptyTypeArgumentListWithNew.errors.txt | 8 + .../reference/parserObjectType5.errors.txt | 5 +- .../reference/parserTypeQuery8.errors.txt | 13 +- tests/baselines/reference/parserTypeQuery8.js | 2 +- .../reference/syntaxErrors.errors.txt | 5 +- tests/baselines/reference/typeCall.js | 10 - tests/baselines/reference/typeCall.symbols | 499 +++++++++--------- tests/baselines/reference/typeCall.types | 23 - tests/cases/compiler/typeCall.ts | 10 - tests/cases/fourslash/underscoreTypings02.ts | 2 +- 22 files changed, 343 insertions(+), 404 deletions(-) create mode 100644 tests/baselines/reference/arrayTypeOfTypeOf.errors.txt create mode 100644 tests/baselines/reference/emptyTypeArgumentList.errors.txt create mode 100644 tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 55e9fdc40ef62..f6a7ea5438dd9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2540,8 +2540,7 @@ namespace ts { if (type.flags & TypeFlags.TypeCall) { const fnNode = typeToTypeNodeHelper((type).function, context); const argNodes = mapToTypeNodes((type).arguments, context); - const typeArgNodes = mapToTypeNodes((type).typeArguments, context); - return createTypeCall(fnNode, typeArgNodes, argNodes); + return createTypeCall(fnNode, argNodes); } Debug.fail("Should be unreachable."); @@ -3314,11 +3313,6 @@ namespace ts { } else if (type.flags & TypeFlags.TypeCall) { writeType((type).function, TypeFormatFlags.None); - if ((type).typeArguments && (type).typeArguments.length) { - writePunctuation(writer, SyntaxKind.LessThanToken); - writeTypeList((type).typeArguments, SyntaxKind.CommaToken); - writePunctuation(writer, SyntaxKind.GreaterThanToken); - } writePunctuation(writer, SyntaxKind.OpenParenToken); writeTypeList((type).arguments, SyntaxKind.CommaToken); writePunctuation(writer, SyntaxKind.CloseParenToken); @@ -5938,9 +5932,8 @@ namespace ts { function getConstraintOfTypeCall(type: TypeCallType): Type { const fn = type.function; - const typeArgs = map(type.typeArguments, getConstraintOfType); const args = map(type.arguments, getConstraintOfType); - const call = createTypeCallType(fn, typeArgs, args); + const call = createTypeCallType(fn, args); return getTypeFromTypeCall(call); } @@ -6815,7 +6808,7 @@ namespace ts { const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, node)); return createTypeReference(type, typeArguments); } - if (node.typeArguments && node.typeArguments.length) { + if (node.typeArguments) { error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); return unknownType; } @@ -6857,7 +6850,7 @@ namespace ts { } return getTypeAliasInstantiation(symbol, typeArguments); } - if (node.typeArguments && node.typeArguments.length) { + if (node.typeArguments) { error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); return unknownType; } @@ -6868,7 +6861,7 @@ namespace ts { * Get type from reference to named type that cannot be generic (enum or type parameter) */ function getTypeFromNonGenericTypeReference(node: TypeReferenceType, symbol: Symbol): Type { - if (node.typeArguments && node.typeArguments.length) { + if (node.typeArguments) { error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol)); return unknownType; } @@ -7575,23 +7568,21 @@ namespace ts { false; } - function createTypeCallType(fn: Type, typeArgs: Type[], args: Type[]): TypeCallType { + function createTypeCallType(fn: Type, args: Type[]): TypeCallType { const type = createType(TypeFlags.TypeCall); type.function = fn; - type.typeArguments = typeArgs; type.arguments = args; return type; } // overlap with typeToTypeNode? function createTypeCallNodeFromType(type: TypeCallType): TypeCallTypeNode { - const node = createNodeBuilder().typeToTypeNode(type); - return node; + return createNodeBuilder().typeToTypeNode(type); } - function getTypeCallType(fn: Type, typeArgs: Type[], args: Type[], node?: TypeCallTypeNode): Type { - const type = createTypeCallType(fn, typeArgs, args); - if (isGenericTypeCallType(fn) || some(typeArgs, isGenericTypeCallType) || some(args, isGenericTypeCallType)) { + function getTypeCallType(fn: Type, args: Type[], node?: TypeCallTypeNode): Type { + const type = createTypeCallType(fn, args); + if (isGenericTypeCallType(fn) || some(args, isGenericTypeCallType)) { return type; } return getTypeFromTypeCall(type, node); @@ -7599,22 +7590,15 @@ namespace ts { function getTypeFromTypeCall(type: TypeCallType, node = createTypeCallNodeFromType(type)): Type { const fn = type.function; - const typeArgs = type.typeArguments; const args = type.arguments; const calls = getSignaturesOfType(fn, SignatureKind.Call); const sig = resolveCall(node, calls, []); if (!sig.typeParameters || !sig.typeParameters.length) { return getReturnTypeOfSignature(sig); } - let signature: Signature; - if (typeArgs && typeArgs.length) { - signature = getSignatureInstantiation(sig, typeArgs); - } - else { - const inferenceContext = createInferenceContext(sig, InferenceFlags.InferUnionTypes); - const types = inferTypeArgumentsForTypeCall(sig, args, inferenceContext); // TODO: add Fn(this: A, B, C) syntax - signature = getSignatureInstantiation(sig, types); - } + const inferenceContext = createInferenceContext(sig, InferenceFlags.InferUnionTypes); + const types = inferTypeArgumentsForTypeCall(sig, args, inferenceContext); // TODO: add Fn(this: A, B, C) syntax + const signature = getSignatureInstantiation(sig, types); return getReturnTypeOfSignature(signature); } @@ -7636,8 +7620,7 @@ namespace ts { const links = getNodeLinks(node); if (!links.resolvedType) { links.resolvedType = getTypeCallType( - getTypeFromTypeNode(node.type), - map(node.typeArguments, getTypeFromTypeNode), + getTypeFromTypeNode(node.function), map(node.arguments, getTypeFromTypeNode), node ); @@ -8466,7 +8449,6 @@ namespace ts { if (type.flags & TypeFlags.TypeCall) { return getTypeCallType( instantiateType((type).function, mapper), - (type).typeArguments, (type).arguments ); } @@ -18904,7 +18886,7 @@ namespace ts { } const type = getTypeFromTypeReference(node); if (type !== unknownType) { - if (node.typeArguments && node.typeArguments.length) { + if (node.typeArguments) { // Do type argument local checks only if referenced type is successfully resolved forEach(node.typeArguments, checkSourceElement); if (produceDiagnostics) { @@ -22603,10 +22585,8 @@ namespace ts { } function checkTypeCallNode(node: TypeCallTypeNode) { - checkGrammarTypeArguments(node, node.typeArguments); - checkSourceElement(node.type); + checkSourceElement(node.function); forEach(node.arguments, checkSourceElement); - forEach(node.typeArguments, checkSourceElement); getTypeFromTypeCallNode(node); } @@ -24490,7 +24470,7 @@ namespace ts { function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray): boolean { return checkGrammarForDisallowedTrailingComma(typeArguments) || - false && checkGrammarForAtLeastOneTypeArgument(node, typeArguments); + checkGrammarForAtLeastOneTypeArgument(node, typeArguments); } function checkGrammarForOmittedArgument(args: NodeArray): boolean { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 6c109628b1419..fb86b39ac7684 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -556,12 +556,7 @@ namespace ts { } function emitTypeCall(node: TypeCallTypeNode) { - emitType(node.type); - if (node.typeArguments && node.typeArguments.length) { - write("<"); - emitCommaList(node.typeArguments, emitType); - write(">"); - } + emitType(node.function); write("("); emitCommaList(node.arguments, emitType); write(")"); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index ad2c85d8553a3..6f1ddb38a14e2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1243,8 +1243,7 @@ namespace ts { } function emitTypeCall(node: TypeCallTypeNode) { - emit(node.type); - emitTypeArguments(node, node.typeArguments); + emit(node.function); emitList(node, node.arguments, ListFormat.CallExpressionArguments); } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f55248f527fee..dcc64f7029ad0 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -888,19 +888,17 @@ namespace ts { : node; } - export function createTypeCall(type: TypeNode, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { + export function createTypeCall(fn: TypeNode, argumentsArray: ReadonlyArray) { const node = createSynthesizedNode(SyntaxKind.TypeCall); - node.type = parenthesizeElementTypeMember(type); - node.typeArguments = asNodeArray(typeArguments); + node.function = parenthesizeElementTypeMember(fn); node.arguments = parenthesizeElementTypeMembers(createNodeArray(argumentsArray)); return node; } - export function updateTypeCall(node: TypeCallTypeNode, type: TypeNode, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { - return node.type !== type - || node.typeArguments !== typeArguments + export function updateTypeCall(node: TypeCallTypeNode, fn: TypeNode, argumentsArray: ReadonlyArray) { + return node.function !== fn || node.arguments !== argumentsArray - ? updateNode(createTypeCall(type, typeArguments, argumentsArray), node) + ? updateNode(createTypeCall(fn, argumentsArray), node) : node; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c8c3ea934e340..fe7f8a9d47e90 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -171,8 +171,7 @@ namespace ts { return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).argumentExpression); case SyntaxKind.TypeCall: - return visitNode(cbNode, (node).type) || - visitNodes(cbNode, cbNodes, (node).typeArguments) || + return visitNode(cbNode, (node).function) || visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: @@ -4247,46 +4246,23 @@ namespace ts { // type equivalent of parseCallExpressionRest function parseTypeCallRest(type?: TypeNode): TypeNode { - // console.log("parseTypeCallRest"); while (true) { type = parseArrayTypeOrHigher(type); // crap, the type may have parsed a semicolon... if (!~[SyntaxKind.ThisType, SyntaxKind.ArrayType, SyntaxKind.TupleType, SyntaxKind.TypeOperator, SyntaxKind.LiteralType, SyntaxKind.NullKeyword, SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword, SyntaxKind.AnyKeyword, SyntaxKind.NumberKeyword, SyntaxKind.ObjectKeyword, SyntaxKind.BooleanKeyword, SyntaxKind.StringKeyword, SyntaxKind.SymbolKeyword, SyntaxKind.ThisKeyword, SyntaxKind.VoidKeyword, SyntaxKind.UndefinedKeyword, SyntaxKind.NullKeyword, SyntaxKind.NeverKeyword].indexOf(type.kind)) { - if (token() === SyntaxKind.LessThanToken) { - // See if this is the start of a generic invocation. If so, consume it and - // keep checking for postfix expressions. Otherwise, it's just a '<' that's - // part of an arithmetic expression. Break out so we consume it higher in the - // stack. - const typeArguments = tryParse(parseTypeArgumentsInExpression); - if (!typeArguments) { - return type; - } - - const call = tryParse(() => parseTypeCall(type)); - if (call) { - type = call; - continue; - } - } - else if (token() === SyntaxKind.OpenParenToken) { + if (token() === SyntaxKind.OpenParenToken) { const call = tryParse(() => parseTypeCall(type)); if (call) { type = call; continue; } } - } return type; } } function parseTypeCall(type: TypeNode) { - let typeArguments: NodeArray; - if (token() === SyntaxKind.LessThanToken) { - typeArguments = tryParse(parseTypeArgumentsInExpression); - } - // if we're in what looks like a function declaration, scram const arg = lookAhead(parseFirstParam); if (arg && arg.type) { @@ -4297,11 +4273,10 @@ namespace ts { return; } const args = parseTypeArgumentList(); - const callExpr = createNode(SyntaxKind.TypeCall, type.pos); - callExpr.type = type; - callExpr.typeArguments = typeArguments; - callExpr.arguments = args; - return finishNode(callExpr); + const typeCall = createNode(SyntaxKind.TypeCall, type.pos); + typeCall.function = type; + typeCall.arguments = args; + return finishNode(typeCall); } function parseFirstParam() { diff --git a/src/compiler/symbolWalker.ts b/src/compiler/symbolWalker.ts index b8828424adbfd..b32977996f4ec 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -116,7 +116,6 @@ namespace ts { function visitTypeCallType(type: TypeCallType): void { visitType(type.function); - visitTypeList(type.typeArguments); visitTypeList(type.arguments); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9c333c7122888..84d46dc590eff 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1498,8 +1498,7 @@ namespace ts { export interface TypeCallTypeNode extends TypeNode { kind: SyntaxKind.TypeCall; - type: TypeNode; - typeArguments?: NodeArray; + function: TypeNode; arguments: NodeArray; } @@ -3414,7 +3413,6 @@ namespace ts { // F(T) types (TypeFlags.TypeCall) export interface TypeCallType extends TypeVariable { function: Type; - typeArguments: Type[]; arguments: Type[]; /* @internal */ resolvedIndexType: IndexType; diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 0592b84a50f03..ef581f307b743 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -448,8 +448,7 @@ namespace ts { case SyntaxKind.TypeCall: return updateTypeCall(node, - visitNode((node).type, visitor, isTypeNode), - nodesVisitor((node).typeArguments, visitor, isTypeNode), + visitNode((node).function, visitor, isTypeNode), nodesVisitor((node).arguments, visitor, isTypeNode)); case SyntaxKind.CallExpression: @@ -1398,7 +1397,7 @@ namespace ts { break; case SyntaxKind.TypeCall: - result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).function, cbNode, result); break; // Enum diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt b/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt new file mode 100644 index 0000000000000..1c37f04be72b8 --- /dev/null +++ b/tests/baselines/reference/arrayTypeOfTypeOf.errors.txt @@ -0,0 +1,28 @@ +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,5): error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,22): error TS1005: '=' expected. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(6,30): error TS1109: Expression expected. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,5): error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,22): error TS1005: '=' expected. +tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts(7,32): error TS1109: Expression expected. + + +==== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts (6 errors) ==== + // array type cannot use typeof. + + var x = 1; + var xs: typeof x[]; // Not an error. This is equivalent to Array + var xs2: typeof Array; + var xs3: typeof Array; + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. + ~ +!!! error TS1005: '=' expected. + ~ +!!! error TS1109: Expression expected. + var xs4: typeof Array; + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'ArrayConstructor'. + ~ +!!! error TS1005: '=' expected. + ~ +!!! error TS1109: Expression expected. \ No newline at end of file diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.js b/tests/baselines/reference/arrayTypeOfTypeOf.js index 74a50b9cc1fc9..f3653346be432 100644 --- a/tests/baselines/reference/arrayTypeOfTypeOf.js +++ b/tests/baselines/reference/arrayTypeOfTypeOf.js @@ -12,5 +12,5 @@ var xs4: typeof Array; var x = 1; var xs; // Not an error. This is equivalent to Array var xs2; -var xs3; -var xs4; +var xs3 = ; +var xs4 = ; diff --git a/tests/baselines/reference/emptyGenericParamList.errors.txt b/tests/baselines/reference/emptyGenericParamList.errors.txt index c0fe9824ab7c4..ed1046d0f4949 100644 --- a/tests/baselines/reference/emptyGenericParamList.errors.txt +++ b/tests/baselines/reference/emptyGenericParamList.errors.txt @@ -1,8 +1,11 @@ tests/cases/compiler/emptyGenericParamList.ts(2,8): error TS2314: Generic type 'I' requires 1 type argument(s). +tests/cases/compiler/emptyGenericParamList.ts(2,9): error TS1099: Type argument list cannot be empty. -==== tests/cases/compiler/emptyGenericParamList.ts (1 errors) ==== +==== tests/cases/compiler/emptyGenericParamList.ts (2 errors) ==== class I {} var x: I<>; ~~~ -!!! error TS2314: Generic type 'I' requires 1 type argument(s). \ No newline at end of file +!!! error TS2314: Generic type 'I' requires 1 type argument(s). + ~~ +!!! error TS1099: Type argument list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/emptyTypeArgumentList.errors.txt b/tests/baselines/reference/emptyTypeArgumentList.errors.txt new file mode 100644 index 0000000000000..74fbe4d328ecc --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentList.errors.txt @@ -0,0 +1,8 @@ +tests/cases/compiler/emptyTypeArgumentList.ts(2,4): error TS1099: Type argument list cannot be empty. + + +==== tests/cases/compiler/emptyTypeArgumentList.ts (1 errors) ==== + function foo() { } + foo<>(); + ~~ +!!! error TS1099: Type argument list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt b/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt new file mode 100644 index 0000000000000..22f196e6e49ef --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt @@ -0,0 +1,8 @@ +tests/cases/compiler/emptyTypeArgumentListWithNew.ts(2,8): error TS1099: Type argument list cannot be empty. + + +==== tests/cases/compiler/emptyTypeArgumentListWithNew.ts (1 errors) ==== + class foo { } + new foo<>(); + ~~ +!!! error TS1099: Type argument list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/parserObjectType5.errors.txt b/tests/baselines/reference/parserObjectType5.errors.txt index 9c74627f42cce..d4db1d2d85c51 100644 --- a/tests/baselines/reference/parserObjectType5.errors.txt +++ b/tests/baselines/reference/parserObjectType5.errors.txt @@ -1,10 +1,13 @@ tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(2,7): error TS2304: Cannot find name 'B'. +tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts(3,7): error TS1005: '(' expected. -==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ObjectTypes/parserObjectType5.ts (2 errors) ==== var v: { A: B ~ !!! error TS2304: Cannot find name 'B'. ; + ~ +!!! error TS1005: '(' expected. }; \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.errors.txt b/tests/baselines/reference/parserTypeQuery8.errors.txt index ab24604ba90fa..4a7098ea8fd3f 100644 --- a/tests/baselines/reference/parserTypeQuery8.errors.txt +++ b/tests/baselines/reference/parserTypeQuery8.errors.txt @@ -1,7 +1,16 @@ tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,15): error TS2304: Cannot find name 'A'. +tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,16): error TS1005: '=' expected. +tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,17): error TS2304: Cannot find name 'B'. +tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts(1,19): error TS1109: Expression expected. -==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Types/parserTypeQuery8.ts (4 errors) ==== var v: typeof A ~ -!!! error TS2304: Cannot find name 'A'. \ No newline at end of file +!!! error TS2304: Cannot find name 'A'. + ~ +!!! error TS1005: '=' expected. + ~ +!!! error TS2304: Cannot find name 'B'. + +!!! error TS1109: Expression expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserTypeQuery8.js b/tests/baselines/reference/parserTypeQuery8.js index f0fd7d6212e76..995ad013c1f0d 100644 --- a/tests/baselines/reference/parserTypeQuery8.js +++ b/tests/baselines/reference/parserTypeQuery8.js @@ -2,4 +2,4 @@ var v: typeof A //// [parserTypeQuery8.js] -var v; +var v = ; diff --git a/tests/baselines/reference/syntaxErrors.errors.txt b/tests/baselines/reference/syntaxErrors.errors.txt index cb639b6d660b7..02ad52a15e519 100644 --- a/tests/baselines/reference/syntaxErrors.errors.txt +++ b/tests/baselines/reference/syntaxErrors.errors.txt @@ -1,11 +1,14 @@ +tests/cases/conformance/jsdoc/badTypeArguments.js(1,15): error TS1099: Type argument list cannot be empty. tests/cases/conformance/jsdoc/badTypeArguments.js(2,22): error TS1009: Trailing comma not allowed. ==== tests/cases/conformance/jsdoc/dummyType.d.ts (0 errors) ==== declare class C { t: T } -==== tests/cases/conformance/jsdoc/badTypeArguments.js (1 errors) ==== +==== tests/cases/conformance/jsdoc/badTypeArguments.js (2 errors) ==== /** @param {C.<>} x */ + ~~ +!!! error TS1099: Type argument list cannot be empty. /** @param {C.} y */ ~ !!! error TS1009: Trailing comma not allowed. diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index e083dbf872ee4..23791126f16e7 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -29,10 +29,6 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -// type k1 = Id('foo'); -// ^ errors, `` is part of the type reference, not the function call -type k2 = Id<>('foo'); // ok, `string` - declare function id(v: T): T; let l = id('foo'); @@ -43,12 +39,6 @@ interface IsPrimitive { type stringIsPrimitive = IsPrimitive(string); // '1', ok type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -type regexpIsPrimitive2 = genericIsPrimitive<>(); -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known - // alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 336a6e2790af1..ed70ee33776d1 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -80,418 +80,395 @@ type j = F5()()['a'](); >j : Symbol(j, Decl(typeCall.ts, 27, 38)) >F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) -// type k1 = Id('foo'); -// ^ errors, `` is part of the type reference, not the function call -type k2 = Id<>('foo'); // ok, `string` ->k2 : Symbol(k2, Decl(typeCall.ts, 28, 23)) ->Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) - declare function id(v: T): T; ->id : Symbol(id, Decl(typeCall.ts, 32, 30)) ->T : Symbol(T, Decl(typeCall.ts, 34, 20)) ->v : Symbol(v, Decl(typeCall.ts, 34, 23)) ->T : Symbol(T, Decl(typeCall.ts, 34, 20)) ->T : Symbol(T, Decl(typeCall.ts, 34, 20)) +>id : Symbol(id, Decl(typeCall.ts, 28, 23)) +>T : Symbol(T, Decl(typeCall.ts, 30, 20)) +>v : Symbol(v, Decl(typeCall.ts, 30, 23)) +>T : Symbol(T, Decl(typeCall.ts, 30, 20)) +>T : Symbol(T, Decl(typeCall.ts, 30, 20)) let l = id('foo'); ->l : Symbol(l, Decl(typeCall.ts, 35, 3)) ->id : Symbol(id, Decl(typeCall.ts, 32, 30)) +>l : Symbol(l, Decl(typeCall.ts, 31, 3)) +>id : Symbol(id, Decl(typeCall.ts, 28, 23)) interface IsPrimitive { ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) (o: object): '0'; ->o : Symbol(o, Decl(typeCall.ts, 38, 3)) +>o : Symbol(o, Decl(typeCall.ts, 34, 3)) (o: any): '1'; ->o : Symbol(o, Decl(typeCall.ts, 39, 3)) +>o : Symbol(o, Decl(typeCall.ts, 35, 3)) } type stringIsPrimitive = IsPrimitive(string); // '1', ok ->stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 40, 1)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) +>stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 36, 1)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok ->regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 41, 45)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) +>regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 37, 45)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 42, 45)) ->T : Symbol(T, Decl(typeCall.ts, 45, 27)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) ->T : Symbol(T, Decl(typeCall.ts, 45, 27)) - -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok ->stringIsPrimitive2 : Symbol(stringIsPrimitive2, Decl(typeCall.ts, 45, 50)) ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 42, 45)) - -type regexpIsPrimitive2 = genericIsPrimitive<>(); ->regexpIsPrimitive2 : Symbol(regexpIsPrimitive2, Decl(typeCall.ts, 46, 57)) ->genericIsPrimitive : Symbol(genericIsPrimitive, Decl(typeCall.ts, 42, 45)) - -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known - // alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 47, 57)) ->T : Symbol(T, Decl(typeCall.ts, 51, 28)) ->v : Symbol(v, Decl(typeCall.ts, 51, 31)) ->T : Symbol(T, Decl(typeCall.ts, 51, 28)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 35, 26)) ->T : Symbol(T, Decl(typeCall.ts, 51, 28)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 38, 45)) +>T : Symbol(T, Decl(typeCall.ts, 41, 28)) +>v : Symbol(v, Decl(typeCall.ts, 41, 31)) +>T : Symbol(T, Decl(typeCall.ts, 41, 28)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) +>T : Symbol(T, Decl(typeCall.ts, 41, 28)) type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok ->stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 51, 55)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 47, 57)) +>stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 41, 55)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 38, 45)) type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) ->regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 52, 54)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 47, 57)) +>regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 42, 54)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 38, 45)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) // fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; ->map : Symbol(map, Decl(typeCall.ts, 53, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 56, 12)) ->v : Symbol(v, Decl(typeCall.ts, 56, 24)) ->T : Symbol(T, Decl(typeCall.ts, 56, 67)) ->O : Symbol(O, Decl(typeCall.ts, 56, 37)) ->k : Symbol(k, Decl(typeCall.ts, 56, 51)) ->T : Symbol(T, Decl(typeCall.ts, 56, 67)) ->T : Symbol(T, Decl(typeCall.ts, 56, 67)) ->fn : Symbol(fn, Decl(typeCall.ts, 56, 71)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 56, 12)) ->obj : Symbol(obj, Decl(typeCall.ts, 56, 78)) ->O : Symbol(O, Decl(typeCall.ts, 56, 37)) ->P : Symbol(P, Decl(typeCall.ts, 56, 93)) ->O : Symbol(O, Decl(typeCall.ts, 56, 37)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 56, 12)) ->O : Symbol(O, Decl(typeCall.ts, 56, 37)) ->P : Symbol(P, Decl(typeCall.ts, 56, 93)) +>map : Symbol(map, Decl(typeCall.ts, 43, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 46, 12)) +>v : Symbol(v, Decl(typeCall.ts, 46, 24)) +>T : Symbol(T, Decl(typeCall.ts, 46, 67)) +>O : Symbol(O, Decl(typeCall.ts, 46, 37)) +>k : Symbol(k, Decl(typeCall.ts, 46, 51)) +>T : Symbol(T, Decl(typeCall.ts, 46, 67)) +>T : Symbol(T, Decl(typeCall.ts, 46, 67)) +>fn : Symbol(fn, Decl(typeCall.ts, 46, 71)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 46, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 46, 78)) +>O : Symbol(O, Decl(typeCall.ts, 46, 37)) +>P : Symbol(P, Decl(typeCall.ts, 46, 93)) +>O : Symbol(O, Decl(typeCall.ts, 46, 37)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 46, 12)) +>O : Symbol(O, Decl(typeCall.ts, 46, 37)) +>P : Symbol(P, Decl(typeCall.ts, 46, 93)) type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : Symbol(z, Decl(typeCall.ts, 56, 119)) ->map : Symbol(map, Decl(typeCall.ts, 53, 53)) ->T : Symbol(T, Decl(typeCall.ts, 57, 14)) ->v : Symbol(v, Decl(typeCall.ts, 57, 17)) ->T : Symbol(T, Decl(typeCall.ts, 57, 14)) ->T : Symbol(T, Decl(typeCall.ts, 57, 14)) ->a : Symbol(a, Decl(typeCall.ts, 57, 32)) ->b : Symbol(b, Decl(typeCall.ts, 57, 38)) ->c : Symbol(c, Decl(typeCall.ts, 57, 44)) +>z : Symbol(z, Decl(typeCall.ts, 46, 119)) +>map : Symbol(map, Decl(typeCall.ts, 43, 53)) +>T : Symbol(T, Decl(typeCall.ts, 47, 14)) +>v : Symbol(v, Decl(typeCall.ts, 47, 17)) +>T : Symbol(T, Decl(typeCall.ts, 47, 14)) +>T : Symbol(T, Decl(typeCall.ts, 47, 14)) +>a : Symbol(a, Decl(typeCall.ts, 47, 32)) +>b : Symbol(b, Decl(typeCall.ts, 47, 38)) +>c : Symbol(c, Decl(typeCall.ts, 47, 44)) // FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) ->T1 : Symbol(T1, Decl(typeCall.ts, 61, 12)) ->v1 : Symbol(v1, Decl(typeCall.ts, 61, 31)) ->T1 : Symbol(T1, Decl(typeCall.ts, 61, 12)) ->k : Symbol(k, Decl(typeCall.ts, 61, 47)) ->T1 : Symbol(T1, Decl(typeCall.ts, 61, 12)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) +>T1 : Symbol(T1, Decl(typeCall.ts, 51, 12)) +>v1 : Symbol(v1, Decl(typeCall.ts, 51, 31)) +>T1 : Symbol(T1, Decl(typeCall.ts, 51, 12)) +>k : Symbol(k, Decl(typeCall.ts, 51, 47)) +>T1 : Symbol(T1, Decl(typeCall.ts, 51, 12)) type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) ->T2 : Symbol(T2, Decl(typeCall.ts, 62, 12)) ->v2 : Symbol(v2, Decl(typeCall.ts, 62, 16)) ->k : Symbol(k, Decl(typeCall.ts, 62, 23)) ->T2 : Symbol(T2, Decl(typeCall.ts, 62, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) +>T2 : Symbol(T2, Decl(typeCall.ts, 52, 12)) +>v2 : Symbol(v2, Decl(typeCall.ts, 52, 16)) +>k : Symbol(k, Decl(typeCall.ts, 52, 23)) +>T2 : Symbol(T2, Decl(typeCall.ts, 52, 12)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) ->T2 : Symbol(T2, Decl(typeCall.ts, 62, 12)) +>T2 : Symbol(T2, Decl(typeCall.ts, 52, 12)) let fn1 = null! as Fn1; ->fn1 : Symbol(fn1, Decl(typeCall.ts, 63, 3)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 53, 3)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) let fn2 = null! as Fn2; ->fn2 : Symbol(fn2, Decl(typeCall.ts, 64, 3)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 54, 3)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) type Fn3 = (v3: T3) => Fn2(Fn1(T3)); ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) ->T3 : Symbol(T3, Decl(typeCall.ts, 65, 12)) ->v3 : Symbol(v3, Decl(typeCall.ts, 65, 33)) ->T3 : Symbol(T3, Decl(typeCall.ts, 65, 12)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) ->T3 : Symbol(T3, Decl(typeCall.ts, 65, 12)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 54, 23)) +>T3 : Symbol(T3, Decl(typeCall.ts, 55, 12)) +>v3 : Symbol(v3, Decl(typeCall.ts, 55, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 55, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) +>T3 : Symbol(T3, Decl(typeCall.ts, 55, 12)) // type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; ->ones : Symbol(ones, Decl(typeCall.ts, 67, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 57, 3)) type Fn4b = Fn3(typeof ones); ->Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 67, 24)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) ->ones : Symbol(ones, Decl(typeCall.ts, 67, 3)) +>Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 57, 24)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 54, 23)) +>ones : Symbol(ones, Decl(typeCall.ts, 57, 3)) // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. type Fn4c = Fn3(1[]); ->Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 68, 29)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 64, 23)) +>Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 58, 29)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 54, 23)) // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); ->y : Symbol(y, Decl(typeCall.ts, 74, 3)) ->fn2 : Symbol(fn2, Decl(typeCall.ts, 64, 3)) ->fn1 : Symbol(fn1, Decl(typeCall.ts, 63, 3)) ->ones : Symbol(ones, Decl(typeCall.ts, 67, 3)) +>y : Symbol(y, Decl(typeCall.ts, 64, 3)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 54, 3)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 53, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 57, 3)) type Y = Fn2(Fn1(1[])); ->Y : Symbol(Y, Decl(typeCall.ts, 74, 23)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 61, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 53)) +>Y : Symbol(Y, Decl(typeCall.ts, 64, 23)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 75, 23)) ->T : Symbol(T, Decl(typeCall.ts, 77, 15)) ->k : Symbol(k, Decl(typeCall.ts, 77, 34)) ->K : Symbol(K, Decl(typeCall.ts, 77, 52)) ->T : Symbol(T, Decl(typeCall.ts, 77, 15)) ->T : Symbol(T, Decl(typeCall.ts, 77, 15)) ->K : Symbol(K, Decl(typeCall.ts, 77, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 65, 23)) +>T : Symbol(T, Decl(typeCall.ts, 67, 15)) +>k : Symbol(k, Decl(typeCall.ts, 67, 34)) +>K : Symbol(K, Decl(typeCall.ts, 67, 52)) +>T : Symbol(T, Decl(typeCall.ts, 67, 15)) +>T : Symbol(T, Decl(typeCall.ts, 67, 15)) +>K : Symbol(K, Decl(typeCall.ts, 67, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 77, 85)) ->T : Symbol(T, Decl(typeCall.ts, 78, 16)) ->k : Symbol(k, Decl(typeCall.ts, 78, 29)) ->K : Symbol(K, Decl(typeCall.ts, 78, 53)) ->T : Symbol(T, Decl(typeCall.ts, 78, 16)) ->T : Symbol(T, Decl(typeCall.ts, 78, 16)) ->K : Symbol(K, Decl(typeCall.ts, 78, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 67, 85)) +>T : Symbol(T, Decl(typeCall.ts, 68, 16)) +>k : Symbol(k, Decl(typeCall.ts, 68, 29)) +>K : Symbol(K, Decl(typeCall.ts, 68, 53)) +>T : Symbol(T, Decl(typeCall.ts, 68, 16)) +>T : Symbol(T, Decl(typeCall.ts, 68, 16)) +>K : Symbol(K, Decl(typeCall.ts, 68, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 78, 82)) ->T : Symbol(T, Decl(typeCall.ts, 79, 22)) ->k : Symbol(k, Decl(typeCall.ts, 79, 35)) ->K : Symbol(K, Decl(typeCall.ts, 79, 65)) ->T : Symbol(T, Decl(typeCall.ts, 79, 22)) ->T : Symbol(T, Decl(typeCall.ts, 79, 22)) ->K : Symbol(K, Decl(typeCall.ts, 79, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 68, 82)) +>T : Symbol(T, Decl(typeCall.ts, 69, 22)) +>k : Symbol(k, Decl(typeCall.ts, 69, 35)) +>K : Symbol(K, Decl(typeCall.ts, 69, 65)) +>T : Symbol(T, Decl(typeCall.ts, 69, 22)) +>T : Symbol(T, Decl(typeCall.ts, 69, 22)) +>K : Symbol(K, Decl(typeCall.ts, 69, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 79, 89)) ->T : Symbol(T, Decl(typeCall.ts, 81, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 81, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 69, 89)) +>T : Symbol(T, Decl(typeCall.ts, 71, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 71, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 82, 5)) ->T : Symbol(T, Decl(typeCall.ts, 81, 12)) +>K : Symbol(K, Decl(typeCall.ts, 72, 5)) +>T : Symbol(T, Decl(typeCall.ts, 71, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 83, 5)) +>key : Symbol(key, Decl(typeCall.ts, 73, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 81, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 71, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 84, 7)) ->T : Symbol(T, Decl(typeCall.ts, 86, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 79, 89)) ->T : Symbol(T, Decl(typeCall.ts, 86, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 74, 7)) +>T : Symbol(T, Decl(typeCall.ts, 76, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 69, 89)) +>T : Symbol(T, Decl(typeCall.ts, 76, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 86, 59)) ->T : Symbol(T, Decl(typeCall.ts, 87, 15)) ->k : Symbol(k, Decl(typeCall.ts, 87, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 87, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 76, 59)) +>T : Symbol(T, Decl(typeCall.ts, 77, 15)) +>k : Symbol(k, Decl(typeCall.ts, 77, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 77, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 88, 5)) ->T : Symbol(T, Decl(typeCall.ts, 87, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 79, 89)) ->T : Symbol(T, Decl(typeCall.ts, 87, 15)) ->K : Symbol(K, Decl(typeCall.ts, 88, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 87, 52)) +>K : Symbol(K, Decl(typeCall.ts, 78, 5)) +>T : Symbol(T, Decl(typeCall.ts, 77, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 69, 89)) +>T : Symbol(T, Decl(typeCall.ts, 77, 15)) +>K : Symbol(K, Decl(typeCall.ts, 78, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 77, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 89, 2)) ->T : Symbol(T, Decl(typeCall.ts, 91, 15)) ->T : Symbol(T, Decl(typeCall.ts, 91, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 79, 2)) +>T : Symbol(T, Decl(typeCall.ts, 81, 15)) +>T : Symbol(T, Decl(typeCall.ts, 81, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 91, 50)) ->T : Symbol(T, Decl(typeCall.ts, 93, 12)) ->K : Symbol(K, Decl(typeCall.ts, 93, 38)) ->T : Symbol(T, Decl(typeCall.ts, 93, 12)) ->T : Symbol(T, Decl(typeCall.ts, 93, 12)) ->K : Symbol(K, Decl(typeCall.ts, 93, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 81, 50)) +>T : Symbol(T, Decl(typeCall.ts, 83, 12)) +>K : Symbol(K, Decl(typeCall.ts, 83, 38)) +>T : Symbol(T, Decl(typeCall.ts, 83, 12)) +>T : Symbol(T, Decl(typeCall.ts, 83, 12)) +>K : Symbol(K, Decl(typeCall.ts, 83, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 93, 66)) ->T : Symbol(T, Decl(typeCall.ts, 94, 12)) ->k : Symbol(k, Decl(typeCall.ts, 94, 31)) ->K : Symbol(K, Decl(typeCall.ts, 94, 61)) ->T : Symbol(T, Decl(typeCall.ts, 94, 12)) ->T : Symbol(T, Decl(typeCall.ts, 94, 12)) ->K : Symbol(K, Decl(typeCall.ts, 94, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 83, 66)) +>T : Symbol(T, Decl(typeCall.ts, 84, 12)) +>k : Symbol(k, Decl(typeCall.ts, 84, 31)) +>K : Symbol(K, Decl(typeCall.ts, 84, 61)) +>T : Symbol(T, Decl(typeCall.ts, 84, 12)) +>T : Symbol(T, Decl(typeCall.ts, 84, 12)) +>K : Symbol(K, Decl(typeCall.ts, 84, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 96, 12)) +>x : Symbol(x, Decl(typeCall.ts, 86, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 97, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 98, 14)) ->value : Symbol(value, Decl(typeCall.ts, 98, 28)) +>z : Symbol(z, Decl(typeCall.ts, 87, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 88, 14)) +>value : Symbol(value, Decl(typeCall.ts, 88, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 99, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 89, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 101, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 77, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 91, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 67, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 102, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 75, 23)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 92, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 65, 23)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 103, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 78, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 93, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 68, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 104, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 94, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 105, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 89, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 95, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 79, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 106, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 96, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 107, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 86, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 97, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 76, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 108, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 91, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 98, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 81, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 109, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 93, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 94, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 99, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 83, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 102, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 113, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 103, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 102, 3)) type Assert any> = T(); ->Assert : Symbol(Assert, Decl(typeCall.ts, 113, 20)) ->T : Symbol(T, Decl(typeCall.ts, 114, 12)) ->T : Symbol(T, Decl(typeCall.ts, 114, 12)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 103, 20)) +>T : Symbol(T, Decl(typeCall.ts, 104, 12)) +>T : Symbol(T, Decl(typeCall.ts, 104, 12)) let c1: Assert; ->c1 : Symbol(c1, Decl(typeCall.ts, 115, 3)) ->Assert : Symbol(Assert, Decl(typeCall.ts, 113, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 112, 3)) +>c1 : Symbol(c1, Decl(typeCall.ts, 105, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 103, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 102, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 115, 26)) ->T : Symbol(T, Decl(typeCall.ts, 117, 24)) ->x : Symbol(x, Decl(typeCall.ts, 117, 45)) ->T : Symbol(T, Decl(typeCall.ts, 117, 24)) ->T : Symbol(T, Decl(typeCall.ts, 117, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 105, 26)) +>T : Symbol(T, Decl(typeCall.ts, 107, 24)) +>x : Symbol(x, Decl(typeCall.ts, 107, 45)) +>T : Symbol(T, Decl(typeCall.ts, 107, 24)) +>T : Symbol(T, Decl(typeCall.ts, 107, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 115, 26)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 105, 26)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 118, 30)) ->T : Symbol(T, Decl(typeCall.ts, 120, 24)) ->x : Symbol(x, Decl(typeCall.ts, 120, 45)) ->a : Symbol(a, Decl(typeCall.ts, 120, 49)) ->T : Symbol(T, Decl(typeCall.ts, 120, 24)) ->T : Symbol(T, Decl(typeCall.ts, 120, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 108, 30)) +>T : Symbol(T, Decl(typeCall.ts, 110, 24)) +>x : Symbol(x, Decl(typeCall.ts, 110, 45)) +>a : Symbol(a, Decl(typeCall.ts, 110, 49)) +>T : Symbol(T, Decl(typeCall.ts, 110, 24)) +>T : Symbol(T, Decl(typeCall.ts, 110, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 118, 30)) ->a : Symbol(a, Decl(typeCall.ts, 121, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 108, 30)) +>a : Symbol(a, Decl(typeCall.ts, 111, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 121, 37)) ->T : Symbol(T, Decl(typeCall.ts, 123, 24)) ->x : Symbol(x, Decl(typeCall.ts, 123, 27)) ->a : Symbol(a, Decl(typeCall.ts, 123, 31)) ->T : Symbol(T, Decl(typeCall.ts, 123, 24)) ->T : Symbol(T, Decl(typeCall.ts, 123, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 111, 37)) +>T : Symbol(T, Decl(typeCall.ts, 113, 24)) +>x : Symbol(x, Decl(typeCall.ts, 113, 27)) +>a : Symbol(a, Decl(typeCall.ts, 113, 31)) +>T : Symbol(T, Decl(typeCall.ts, 113, 24)) +>T : Symbol(T, Decl(typeCall.ts, 113, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 121, 37)) ->a : Symbol(a, Decl(typeCall.ts, 124, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 111, 37)) +>a : Symbol(a, Decl(typeCall.ts, 114, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 125, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 121, 37)) ->a : Symbol(a, Decl(typeCall.ts, 125, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 115, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 111, 37)) +>a : Symbol(a, Decl(typeCall.ts, 115, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 125, 58)) ->T : Symbol(T, Decl(typeCall.ts, 127, 24)) ->x : Symbol(x, Decl(typeCall.ts, 127, 27)) ->T : Symbol(T, Decl(typeCall.ts, 127, 24)) ->y : Symbol(y, Decl(typeCall.ts, 127, 32)) ->T : Symbol(T, Decl(typeCall.ts, 127, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 115, 58)) +>T : Symbol(T, Decl(typeCall.ts, 117, 24)) +>x : Symbol(x, Decl(typeCall.ts, 117, 27)) +>T : Symbol(T, Decl(typeCall.ts, 117, 24)) +>y : Symbol(y, Decl(typeCall.ts, 117, 32)) +>T : Symbol(T, Decl(typeCall.ts, 117, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 125, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 115, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 128, 19)) ->T : Symbol(T, Decl(typeCall.ts, 130, 23)) ->x : Symbol(x, Decl(typeCall.ts, 130, 26)) ->T : Symbol(T, Decl(typeCall.ts, 130, 23)) ->y : Symbol(y, Decl(typeCall.ts, 130, 31)) ->T : Symbol(T, Decl(typeCall.ts, 130, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 118, 19)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>x : Symbol(x, Decl(typeCall.ts, 120, 26)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>y : Symbol(y, Decl(typeCall.ts, 120, 31)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 131, 9)) ->T : Symbol(T, Decl(typeCall.ts, 130, 23)) ->x : Symbol(x, Decl(typeCall.ts, 130, 26)) +>a : Symbol(a, Decl(typeCall.ts, 121, 9)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>x : Symbol(x, Decl(typeCall.ts, 120, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 132, 9)) ->T : Symbol(T, Decl(typeCall.ts, 130, 23)) ->y : Symbol(y, Decl(typeCall.ts, 130, 31)) +>b : Symbol(b, Decl(typeCall.ts, 122, 9)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>y : Symbol(y, Decl(typeCall.ts, 120, 31)) } function comparability(x: T, y: () => T) { ->comparability : Symbol(comparability, Decl(typeCall.ts, 133, 1)) ->T : Symbol(T, Decl(typeCall.ts, 135, 23)) ->x : Symbol(x, Decl(typeCall.ts, 135, 26)) ->T : Symbol(T, Decl(typeCall.ts, 135, 23)) ->y : Symbol(y, Decl(typeCall.ts, 135, 31)) ->T : Symbol(T, Decl(typeCall.ts, 135, 23)) +>comparability : Symbol(comparability, Decl(typeCall.ts, 123, 1)) +>T : Symbol(T, Decl(typeCall.ts, 125, 23)) +>x : Symbol(x, Decl(typeCall.ts, 125, 26)) +>T : Symbol(T, Decl(typeCall.ts, 125, 23)) +>y : Symbol(y, Decl(typeCall.ts, 125, 31)) +>T : Symbol(T, Decl(typeCall.ts, 125, 23)) x === x; ->x : Symbol(x, Decl(typeCall.ts, 135, 26)) ->x : Symbol(x, Decl(typeCall.ts, 135, 26)) +>x : Symbol(x, Decl(typeCall.ts, 125, 26)) +>x : Symbol(x, Decl(typeCall.ts, 125, 26)) y === y; ->y : Symbol(y, Decl(typeCall.ts, 135, 31)) ->y : Symbol(y, Decl(typeCall.ts, 135, 31)) +>y : Symbol(y, Decl(typeCall.ts, 125, 31)) +>y : Symbol(y, Decl(typeCall.ts, 125, 31)) // x === y; // rightfully errors } diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index d9b89dca990f1..2dd1ac5b77858 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -81,12 +81,6 @@ type j = F5()()['a'](); >j : 1 >F5 : F5 -// type k1 = Id('foo'); -// ^ errors, `` is part of the type reference, not the function call -type k2 = Id<>('foo'); // ok, `string` ->k2 : "foo" ->Id : Id - declare function id(v: T): T; >id : (v: T) => T >T : T @@ -118,23 +112,6 @@ type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok >IsPrimitive : IsPrimitive >RegExp : RegExp -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); ->genericIsPrimitive : genericIsPrimitive ->T : T ->IsPrimitive : IsPrimitive ->T : T - -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok ->stringIsPrimitive2 : IsPrimitive(T) ->genericIsPrimitive : genericIsPrimitive - -type regexpIsPrimitive2 = genericIsPrimitive<>(); ->regexpIsPrimitive2 : IsPrimitive(T) ->genericIsPrimitive : genericIsPrimitive - -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known - // alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); >genericIsPrimitive3 : genericIsPrimitive3 diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 7c045cffed38f..56028983053b0 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -32,10 +32,6 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -// type k1 = Id('foo'); -// ^ errors, `` is part of the type reference, not the function call -type k2 = Id<>('foo'); // ok, `string` - declare function id(v: T): T; let l = id('foo'); @@ -46,12 +42,6 @@ interface IsPrimitive { type stringIsPrimitive = IsPrimitive(string); // '1', ok type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok -// explicit type arguments need to go after the type arguments of the type reference, empty `<>` if n/a -type genericIsPrimitive = () => IsPrimitive(T); -type stringIsPrimitive2 = genericIsPrimitive<>(); // '1', ok -type regexpIsPrimitive2 = genericIsPrimitive<>(); -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known - // alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok diff --git a/tests/cases/fourslash/underscoreTypings02.ts b/tests/cases/fourslash/underscoreTypings02.ts index f1a44925a87df..be7d20427e229 100644 --- a/tests/cases/fourslash/underscoreTypings02.ts +++ b/tests/cases/fourslash/underscoreTypings02.ts @@ -20,4 +20,4 @@ //// } goTo.position(0); -verify.numberOfErrorsInCurrentFile(1); +verify.numberOfErrorsInCurrentFile(2); From 0e4c3592d3295a6549e3984c7b79383a871ce8f6 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sat, 9 Sep 2017 21:19:46 +0800 Subject: [PATCH 13/25] resolve type call, generalize functions to fix synthetic node workaround --- src/compiler/checker.ts | 47 +- src/compiler/types.ts | 2 + .../baselines/reference/overloadSelection.js | 4 +- .../reference/overloadSelection.symbols | 9 +- .../reference/overloadSelection.types | 7 +- tests/baselines/reference/typeCall.js | 18 +- tests/baselines/reference/typeCall.symbols | 487 +++++++++--------- tests/baselines/reference/typeCall.types | 39 +- tests/cases/compiler/overloadSelection.ts | 3 +- tests/cases/compiler/typeCall.ts | 15 +- 10 files changed, 287 insertions(+), 344 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f6a7ea5438dd9..c7a8c272b2af9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7628,10 +7628,6 @@ namespace ts { return links.resolvedType; } - // null! as type - function typeNodeToExpression(type: TypeNode): Expression { - return createAsExpression(createNonNullExpression(createNull()), type); - } function createIndexedAccessType(objectType: Type, indexType: Type) { const type = createType(TypeFlags.IndexedAccess); @@ -7826,7 +7822,7 @@ namespace ts { if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers const aliasSymbol = getAliasSymbolForTypeNode(node); - if (node.symbol.members.size === 0 && !aliasSymbol) { + if (!node.symbol || node.symbol.members.size === 0 && !aliasSymbol) { links.resolvedType = emptyTypeLiteralType; } else { @@ -7843,7 +7839,7 @@ namespace ts { } function getAliasSymbolForTypeNode(node: TypeNode) { - return node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined; + return node.parent && node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined; } function getAliasTypeArgumentsForTypeNode(node: TypeNode) { @@ -8449,7 +8445,7 @@ namespace ts { if (type.flags & TypeFlags.TypeCall) { return getTypeCallType( instantiateType((type).function, mapper), - (type).arguments + instantiateTypes((type).arguments, mapper) ); } return type; @@ -13134,7 +13130,7 @@ namespace ts { // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter. function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type { - const args = getEffectiveCallArguments(callTarget); + const args = >getEffectiveCallArguments(callTarget); const argIndex = indexOf(args, arg); if (argIndex >= 0) { // If we're already in the process of resolving the given signature, don't resolve again as @@ -15205,7 +15201,7 @@ namespace ts { } } - function getSpreadArgumentIndex(args: ReadonlyArray): number { + function getSpreadArgumentIndex(args: Arguments): number { for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg && arg.kind === SyntaxKind.SpreadElement) { @@ -15215,7 +15211,7 @@ namespace ts { return -1; } - function hasCorrectArity(node: CallLike, args: ReadonlyArray, signature: Signature, signatureHelpTrailingComma = false) { + function hasCorrectArity(node: CallLike, args: Arguments, signature: Signature, signatureHelpTrailingComma = false) { let argCount: number; // Apparent number of arguments we will have in this call let typeArguments: NodeArray; // Type arguments (undefined if none) let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments @@ -15326,7 +15322,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLike, signature: Signature, args: ReadonlyArray, excludeArgument: boolean[], context: InferenceContext): Type[] { + function inferTypeArguments(node: CallLike, signature: Signature, args: Arguments, excludeArgument: boolean[], context: InferenceContext): Type[] { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (const inference of context.inferences) { // As an optimization, we don't have to clear (and later recompute) inferred types @@ -15379,17 +15375,17 @@ namespace ts { for (let i = 0; i < argCount; i++) { const arg = getEffectiveArgument(node, args, i); // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. - if (arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { + if (isTypeCallTypeNode(node) || arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); let argType = getEffectiveArgumentType(node, i); // If the effective argument type is 'undefined', there is no synthetic type // for the argument. In that case, we should check the argument. - if (argType === undefined) { + if (!isTypeCallTypeNode(node) && argType === undefined) { // For context sensitive arguments we pass the identityMapper, which is a signal to treat all // context sensitive function expressions as wildcards const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - argType = checkExpressionWithContextualType(arg, paramType, mapper); + argType = checkExpressionWithContextualType(arg, paramType, mapper); } inferTypes(context.inferences, argType, paramType); @@ -15401,13 +15397,13 @@ namespace ts { // as we construct types for contextually typed parameters) // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. - if (excludeArgument) { + if (!isTypeCallTypeNode(node) && excludeArgument) { for (let i = 0; i < argCount; i++) { // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { const arg = args[i]; const paramType = getTypeAtPosition(signature, i); - inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType); + inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType); } } } @@ -15480,7 +15476,7 @@ namespace ts { function checkApplicableSignature( node: CallLike, - args: ReadonlyArray, + args: Arguments, signature: Signature, relation: Map, excludeArgument: boolean[], @@ -15504,9 +15500,9 @@ namespace ts { const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; const argCount = getEffectiveArgumentCount(node, args, signature); for (let i = 0; i < argCount; i++) { - const arg = getEffectiveArgument(node, args, i); + const arg = getEffectiveArgument(node, args, i); // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. - if (arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { + if (!isTypeCallTypeNode(node) && arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { // Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter) const paramType = getTypeAtPosition(signature, i); // If the effective argument type is undefined, there is no synthetic type for the argument. @@ -15552,7 +15548,7 @@ namespace ts { * If 'node' is a Decorator, the argument list will be `undefined`, and its arguments and types * will be supplied from calls to `getEffectiveArgumentCount` and `getEffectiveArgumentType`. */ - function getEffectiveCallArguments(node: CallLike): ReadonlyArray { + function getEffectiveCallArguments(node: CallLike): Arguments { if (node.kind === SyntaxKind.TaggedTemplateExpression) { const template = (node).template; const args: Expression[] = [undefined]; @@ -15572,9 +15568,6 @@ namespace ts { else if (isJsxOpeningLikeElement(node)) { return node.attributes.properties.length > 0 ? [node.attributes] : emptyArray; } - else if (isTypeCallTypeNode(node)) { - return map(>node.arguments, (arg: TypeNode) => typeNodeToExpression(arg)) || emptyArray; - } else { return node.arguments || emptyArray; } @@ -15594,7 +15587,7 @@ namespace ts { * us to match a property decorator. * Otherwise, the argument count is the length of the 'args' array. */ - function getEffectiveArgumentCount(node: CallLike, args: ReadonlyArray, signature: Signature) { + function getEffectiveArgumentCount(node: CallLike, args: Arguments, signature: Signature) { if (node.kind === SyntaxKind.Decorator) { switch (node.parent.kind) { case SyntaxKind.ClassDeclaration: @@ -15829,7 +15822,7 @@ namespace ts { /** * Gets the effective argument expression for an argument in a call expression. */ - function getEffectiveArgument(node: CallLike, args: ReadonlyArray, argIndex: number) { + function getEffectiveArgument(node: CallLike, args: Arguments, argIndex: number) { // For a decorator or the first argument of a tagged template expression we return undefined. if (node.kind === SyntaxKind.Decorator || (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression)) { @@ -15899,11 +15892,11 @@ namespace ts { const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; let excludeArgument: boolean[]; let excludeCount = 0; - if (!isDecorator && !isSingleNonGenericCandidate) { + if (!isDecorator && !isSingleNonGenericCandidate && !isTypeCallTypeNode(node)) { // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { + if (isContextSensitive(args[i])) { if (!excludeArgument) { excludeArgument = new Array(args.length); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 84d46dc590eff..cb423bc3bd112 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -618,6 +618,8 @@ namespace ts { export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; + export type Arguments = ReadonlyArray | ReadonlyArray; + export interface Declaration extends Node { _declarationBrand: any; } diff --git a/tests/baselines/reference/overloadSelection.js b/tests/baselines/reference/overloadSelection.js index a47f65ea88ac1..dbaf6bf61f2da 100644 --- a/tests/baselines/reference/overloadSelection.js +++ b/tests/baselines/reference/overloadSelection.js @@ -3,10 +3,8 @@ interface Match { (o: object): 0; (o: any): 1; } -type Wrap = (v: T) => Match(T); +type Wrap = (v: T) => Match(T); type A = Wrap(RegExp); -// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) //// [overloadSelection.js] -// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) diff --git a/tests/baselines/reference/overloadSelection.symbols b/tests/baselines/reference/overloadSelection.symbols index fc3aa50564e30..913010f4de8f6 100644 --- a/tests/baselines/reference/overloadSelection.symbols +++ b/tests/baselines/reference/overloadSelection.symbols @@ -8,19 +8,16 @@ interface Match { (o: any): 1; >o : Symbol(o, Decl(overloadSelection.ts, 2, 3)) } -type Wrap = (v: T) => Match(T); +type Wrap = (v: T) => Match(T); >Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) >T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) ->RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->v : Symbol(v, Decl(overloadSelection.ts, 4, 25)) +>v : Symbol(v, Decl(overloadSelection.ts, 4, 16)) >T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) >Match : Symbol(Match, Decl(overloadSelection.ts, 0, 0)) >T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) type A = Wrap(RegExp); ->A : Symbol(A, Decl(overloadSelection.ts, 4, 43)) +>A : Symbol(A, Decl(overloadSelection.ts, 4, 34)) >Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) -// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) - diff --git a/tests/baselines/reference/overloadSelection.types b/tests/baselines/reference/overloadSelection.types index 997fd7ab9e044..3084fa5e9fabe 100644 --- a/tests/baselines/reference/overloadSelection.types +++ b/tests/baselines/reference/overloadSelection.types @@ -8,19 +8,16 @@ interface Match { (o: any): 1; >o : any } -type Wrap = (v: T) => Match(T); +type Wrap = (v: T) => Match(T); >Wrap : Wrap >T : T ->RegExp : RegExp >v : T >T : T >Match : Match >T : T type A = Wrap(RegExp); ->A : Match(T) +>A : 0 >Wrap : Wrap >RegExp : RegExp -// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) - diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 23791126f16e7..cc974244c08c3 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -29,25 +29,20 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -declare function id(v: T): T; -let l = id('foo'); - interface IsPrimitive { (o: object): '0'; (o: any): '1'; } -type stringIsPrimitive = IsPrimitive(string); // '1', ok -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +type stringIsPrimitive = IsPrimitive(string); +type regexpIsPrimitive = IsPrimitive(RegExp); // alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type stringIsPrimitive3 = genericIsPrimitive3(string); type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; @@ -58,9 +53,9 @@ type Fn3 = (v3: T3) => Fn2(Fn1(T3)); // type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; type Fn4b = Fn3(typeof ones); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); @@ -156,12 +151,11 @@ function comparability(x: T, y: () => T) { //// [typeCall.js] var a = 'foo'; -var l = id('foo'); var fn1 = null; var fn2 = null; // type Fn4 = Fn3(1); // errors, ok var ones = null; -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok var y = fn2(fn1(ones)); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index ed70ee33776d1..c831b2d4486fc 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -80,395 +80,380 @@ type j = F5()()['a'](); >j : Symbol(j, Decl(typeCall.ts, 27, 38)) >F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) -declare function id(v: T): T; ->id : Symbol(id, Decl(typeCall.ts, 28, 23)) ->T : Symbol(T, Decl(typeCall.ts, 30, 20)) ->v : Symbol(v, Decl(typeCall.ts, 30, 23)) ->T : Symbol(T, Decl(typeCall.ts, 30, 20)) ->T : Symbol(T, Decl(typeCall.ts, 30, 20)) - -let l = id('foo'); ->l : Symbol(l, Decl(typeCall.ts, 31, 3)) ->id : Symbol(id, Decl(typeCall.ts, 28, 23)) - interface IsPrimitive { ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) (o: object): '0'; ->o : Symbol(o, Decl(typeCall.ts, 34, 3)) +>o : Symbol(o, Decl(typeCall.ts, 31, 3)) (o: any): '1'; ->o : Symbol(o, Decl(typeCall.ts, 35, 3)) +>o : Symbol(o, Decl(typeCall.ts, 32, 3)) } -type stringIsPrimitive = IsPrimitive(string); // '1', ok ->stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 36, 1)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) +type stringIsPrimitive = IsPrimitive(string); +>stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 33, 1)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok ->regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 37, 45)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) +type regexpIsPrimitive = IsPrimitive(RegExp); +>regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 34, 45)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) // alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 38, 45)) ->T : Symbol(T, Decl(typeCall.ts, 41, 28)) ->v : Symbol(v, Decl(typeCall.ts, 41, 31)) ->T : Symbol(T, Decl(typeCall.ts, 41, 28)) ->IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 31, 26)) ->T : Symbol(T, Decl(typeCall.ts, 41, 28)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 35, 45)) +>T : Symbol(T, Decl(typeCall.ts, 38, 28)) +>v : Symbol(v, Decl(typeCall.ts, 38, 31)) +>T : Symbol(T, Decl(typeCall.ts, 38, 28)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) +>T : Symbol(T, Decl(typeCall.ts, 38, 28)) -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok ->stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 41, 55)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 38, 45)) +type stringIsPrimitive3 = genericIsPrimitive3(string); +>stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 38, 55)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 35, 45)) type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) ->regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 42, 54)) ->genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 38, 45)) +>regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 39, 54)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 35, 45)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known - type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; ->map : Symbol(map, Decl(typeCall.ts, 43, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 46, 12)) ->v : Symbol(v, Decl(typeCall.ts, 46, 24)) ->T : Symbol(T, Decl(typeCall.ts, 46, 67)) ->O : Symbol(O, Decl(typeCall.ts, 46, 37)) ->k : Symbol(k, Decl(typeCall.ts, 46, 51)) ->T : Symbol(T, Decl(typeCall.ts, 46, 67)) ->T : Symbol(T, Decl(typeCall.ts, 46, 67)) ->fn : Symbol(fn, Decl(typeCall.ts, 46, 71)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 46, 12)) ->obj : Symbol(obj, Decl(typeCall.ts, 46, 78)) ->O : Symbol(O, Decl(typeCall.ts, 46, 37)) ->P : Symbol(P, Decl(typeCall.ts, 46, 93)) ->O : Symbol(O, Decl(typeCall.ts, 46, 37)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 46, 12)) ->O : Symbol(O, Decl(typeCall.ts, 46, 37)) ->P : Symbol(P, Decl(typeCall.ts, 46, 93)) +>map : Symbol(map, Decl(typeCall.ts, 40, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 42, 12)) +>v : Symbol(v, Decl(typeCall.ts, 42, 24)) +>T : Symbol(T, Decl(typeCall.ts, 42, 67)) +>O : Symbol(O, Decl(typeCall.ts, 42, 37)) +>k : Symbol(k, Decl(typeCall.ts, 42, 51)) +>T : Symbol(T, Decl(typeCall.ts, 42, 67)) +>T : Symbol(T, Decl(typeCall.ts, 42, 67)) +>fn : Symbol(fn, Decl(typeCall.ts, 42, 71)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 42, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 42, 78)) +>O : Symbol(O, Decl(typeCall.ts, 42, 37)) +>P : Symbol(P, Decl(typeCall.ts, 42, 93)) +>O : Symbol(O, Decl(typeCall.ts, 42, 37)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 42, 12)) +>O : Symbol(O, Decl(typeCall.ts, 42, 37)) +>P : Symbol(P, Decl(typeCall.ts, 42, 93)) type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : Symbol(z, Decl(typeCall.ts, 46, 119)) ->map : Symbol(map, Decl(typeCall.ts, 43, 53)) ->T : Symbol(T, Decl(typeCall.ts, 47, 14)) ->v : Symbol(v, Decl(typeCall.ts, 47, 17)) ->T : Symbol(T, Decl(typeCall.ts, 47, 14)) ->T : Symbol(T, Decl(typeCall.ts, 47, 14)) ->a : Symbol(a, Decl(typeCall.ts, 47, 32)) ->b : Symbol(b, Decl(typeCall.ts, 47, 38)) ->c : Symbol(c, Decl(typeCall.ts, 47, 44)) - -// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. +>z : Symbol(z, Decl(typeCall.ts, 42, 119)) +>map : Symbol(map, Decl(typeCall.ts, 40, 53)) +>T : Symbol(T, Decl(typeCall.ts, 43, 14)) +>v : Symbol(v, Decl(typeCall.ts, 43, 17)) +>T : Symbol(T, Decl(typeCall.ts, 43, 14)) +>T : Symbol(T, Decl(typeCall.ts, 43, 14)) +>a : Symbol(a, Decl(typeCall.ts, 43, 32)) +>b : Symbol(b, Decl(typeCall.ts, 43, 38)) +>c : Symbol(c, Decl(typeCall.ts, 43, 44)) // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) ->T1 : Symbol(T1, Decl(typeCall.ts, 51, 12)) ->v1 : Symbol(v1, Decl(typeCall.ts, 51, 31)) ->T1 : Symbol(T1, Decl(typeCall.ts, 51, 12)) ->k : Symbol(k, Decl(typeCall.ts, 51, 47)) ->T1 : Symbol(T1, Decl(typeCall.ts, 51, 12)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) +>T1 : Symbol(T1, Decl(typeCall.ts, 46, 12)) +>v1 : Symbol(v1, Decl(typeCall.ts, 46, 31)) +>T1 : Symbol(T1, Decl(typeCall.ts, 46, 12)) +>k : Symbol(k, Decl(typeCall.ts, 46, 47)) +>T1 : Symbol(T1, Decl(typeCall.ts, 46, 12)) type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) ->T2 : Symbol(T2, Decl(typeCall.ts, 52, 12)) ->v2 : Symbol(v2, Decl(typeCall.ts, 52, 16)) ->k : Symbol(k, Decl(typeCall.ts, 52, 23)) ->T2 : Symbol(T2, Decl(typeCall.ts, 52, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) +>T2 : Symbol(T2, Decl(typeCall.ts, 47, 12)) +>v2 : Symbol(v2, Decl(typeCall.ts, 47, 16)) +>k : Symbol(k, Decl(typeCall.ts, 47, 23)) +>T2 : Symbol(T2, Decl(typeCall.ts, 47, 12)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) ->T2 : Symbol(T2, Decl(typeCall.ts, 52, 12)) +>T2 : Symbol(T2, Decl(typeCall.ts, 47, 12)) let fn1 = null! as Fn1; ->fn1 : Symbol(fn1, Decl(typeCall.ts, 53, 3)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 48, 3)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) let fn2 = null! as Fn2; ->fn2 : Symbol(fn2, Decl(typeCall.ts, 54, 3)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 49, 3)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) type Fn3 = (v3: T3) => Fn2(Fn1(T3)); ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 54, 23)) ->T3 : Symbol(T3, Decl(typeCall.ts, 55, 12)) ->v3 : Symbol(v3, Decl(typeCall.ts, 55, 33)) ->T3 : Symbol(T3, Decl(typeCall.ts, 55, 12)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) ->T3 : Symbol(T3, Decl(typeCall.ts, 55, 12)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 49, 23)) +>T3 : Symbol(T3, Decl(typeCall.ts, 50, 12)) +>v3 : Symbol(v3, Decl(typeCall.ts, 50, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 50, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) +>T3 : Symbol(T3, Decl(typeCall.ts, 50, 12)) // type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; ->ones : Symbol(ones, Decl(typeCall.ts, 57, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 52, 3)) type Fn4b = Fn3(typeof ones); ->Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 57, 24)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 54, 23)) ->ones : Symbol(ones, Decl(typeCall.ts, 57, 3)) +>Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 52, 24)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 49, 23)) +>ones : Symbol(ones, Decl(typeCall.ts, 52, 3)) -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); ->Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 58, 29)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 54, 23)) +>Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 53, 29)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 49, 23)) -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); ->y : Symbol(y, Decl(typeCall.ts, 64, 3)) ->fn2 : Symbol(fn2, Decl(typeCall.ts, 54, 3)) ->fn1 : Symbol(fn1, Decl(typeCall.ts, 53, 3)) ->ones : Symbol(ones, Decl(typeCall.ts, 57, 3)) +>y : Symbol(y, Decl(typeCall.ts, 59, 3)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 49, 3)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 48, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 52, 3)) type Y = Fn2(Fn1(1[])); ->Y : Symbol(Y, Decl(typeCall.ts, 64, 23)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 51, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 47, 53)) +>Y : Symbol(Y, Decl(typeCall.ts, 59, 23)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 65, 23)) ->T : Symbol(T, Decl(typeCall.ts, 67, 15)) ->k : Symbol(k, Decl(typeCall.ts, 67, 34)) ->K : Symbol(K, Decl(typeCall.ts, 67, 52)) ->T : Symbol(T, Decl(typeCall.ts, 67, 15)) ->T : Symbol(T, Decl(typeCall.ts, 67, 15)) ->K : Symbol(K, Decl(typeCall.ts, 67, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 60, 23)) +>T : Symbol(T, Decl(typeCall.ts, 62, 15)) +>k : Symbol(k, Decl(typeCall.ts, 62, 34)) +>K : Symbol(K, Decl(typeCall.ts, 62, 52)) +>T : Symbol(T, Decl(typeCall.ts, 62, 15)) +>T : Symbol(T, Decl(typeCall.ts, 62, 15)) +>K : Symbol(K, Decl(typeCall.ts, 62, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 67, 85)) ->T : Symbol(T, Decl(typeCall.ts, 68, 16)) ->k : Symbol(k, Decl(typeCall.ts, 68, 29)) ->K : Symbol(K, Decl(typeCall.ts, 68, 53)) ->T : Symbol(T, Decl(typeCall.ts, 68, 16)) ->T : Symbol(T, Decl(typeCall.ts, 68, 16)) ->K : Symbol(K, Decl(typeCall.ts, 68, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 62, 85)) +>T : Symbol(T, Decl(typeCall.ts, 63, 16)) +>k : Symbol(k, Decl(typeCall.ts, 63, 29)) +>K : Symbol(K, Decl(typeCall.ts, 63, 53)) +>T : Symbol(T, Decl(typeCall.ts, 63, 16)) +>T : Symbol(T, Decl(typeCall.ts, 63, 16)) +>K : Symbol(K, Decl(typeCall.ts, 63, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 68, 82)) ->T : Symbol(T, Decl(typeCall.ts, 69, 22)) ->k : Symbol(k, Decl(typeCall.ts, 69, 35)) ->K : Symbol(K, Decl(typeCall.ts, 69, 65)) ->T : Symbol(T, Decl(typeCall.ts, 69, 22)) ->T : Symbol(T, Decl(typeCall.ts, 69, 22)) ->K : Symbol(K, Decl(typeCall.ts, 69, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 63, 82)) +>T : Symbol(T, Decl(typeCall.ts, 64, 22)) +>k : Symbol(k, Decl(typeCall.ts, 64, 35)) +>K : Symbol(K, Decl(typeCall.ts, 64, 65)) +>T : Symbol(T, Decl(typeCall.ts, 64, 22)) +>T : Symbol(T, Decl(typeCall.ts, 64, 22)) +>K : Symbol(K, Decl(typeCall.ts, 64, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 69, 89)) ->T : Symbol(T, Decl(typeCall.ts, 71, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 71, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 64, 89)) +>T : Symbol(T, Decl(typeCall.ts, 66, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 66, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 72, 5)) ->T : Symbol(T, Decl(typeCall.ts, 71, 12)) +>K : Symbol(K, Decl(typeCall.ts, 67, 5)) +>T : Symbol(T, Decl(typeCall.ts, 66, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 73, 5)) +>key : Symbol(key, Decl(typeCall.ts, 68, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 71, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 66, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 74, 7)) ->T : Symbol(T, Decl(typeCall.ts, 76, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 69, 89)) ->T : Symbol(T, Decl(typeCall.ts, 76, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 69, 7)) +>T : Symbol(T, Decl(typeCall.ts, 71, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 64, 89)) +>T : Symbol(T, Decl(typeCall.ts, 71, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 76, 59)) ->T : Symbol(T, Decl(typeCall.ts, 77, 15)) ->k : Symbol(k, Decl(typeCall.ts, 77, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 77, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 71, 59)) +>T : Symbol(T, Decl(typeCall.ts, 72, 15)) +>k : Symbol(k, Decl(typeCall.ts, 72, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 72, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 78, 5)) ->T : Symbol(T, Decl(typeCall.ts, 77, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 69, 89)) ->T : Symbol(T, Decl(typeCall.ts, 77, 15)) ->K : Symbol(K, Decl(typeCall.ts, 78, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 77, 52)) +>K : Symbol(K, Decl(typeCall.ts, 73, 5)) +>T : Symbol(T, Decl(typeCall.ts, 72, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 64, 89)) +>T : Symbol(T, Decl(typeCall.ts, 72, 15)) +>K : Symbol(K, Decl(typeCall.ts, 73, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 72, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 79, 2)) ->T : Symbol(T, Decl(typeCall.ts, 81, 15)) ->T : Symbol(T, Decl(typeCall.ts, 81, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 74, 2)) +>T : Symbol(T, Decl(typeCall.ts, 76, 15)) +>T : Symbol(T, Decl(typeCall.ts, 76, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 81, 50)) ->T : Symbol(T, Decl(typeCall.ts, 83, 12)) ->K : Symbol(K, Decl(typeCall.ts, 83, 38)) ->T : Symbol(T, Decl(typeCall.ts, 83, 12)) ->T : Symbol(T, Decl(typeCall.ts, 83, 12)) ->K : Symbol(K, Decl(typeCall.ts, 83, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 76, 50)) +>T : Symbol(T, Decl(typeCall.ts, 78, 12)) +>K : Symbol(K, Decl(typeCall.ts, 78, 38)) +>T : Symbol(T, Decl(typeCall.ts, 78, 12)) +>T : Symbol(T, Decl(typeCall.ts, 78, 12)) +>K : Symbol(K, Decl(typeCall.ts, 78, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 83, 66)) ->T : Symbol(T, Decl(typeCall.ts, 84, 12)) ->k : Symbol(k, Decl(typeCall.ts, 84, 31)) ->K : Symbol(K, Decl(typeCall.ts, 84, 61)) ->T : Symbol(T, Decl(typeCall.ts, 84, 12)) ->T : Symbol(T, Decl(typeCall.ts, 84, 12)) ->K : Symbol(K, Decl(typeCall.ts, 84, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 78, 66)) +>T : Symbol(T, Decl(typeCall.ts, 79, 12)) +>k : Symbol(k, Decl(typeCall.ts, 79, 31)) +>K : Symbol(K, Decl(typeCall.ts, 79, 61)) +>T : Symbol(T, Decl(typeCall.ts, 79, 12)) +>T : Symbol(T, Decl(typeCall.ts, 79, 12)) +>K : Symbol(K, Decl(typeCall.ts, 79, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 86, 12)) +>x : Symbol(x, Decl(typeCall.ts, 81, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 87, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 88, 14)) ->value : Symbol(value, Decl(typeCall.ts, 88, 28)) +>z : Symbol(z, Decl(typeCall.ts, 82, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 83, 14)) +>value : Symbol(value, Decl(typeCall.ts, 83, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 89, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 84, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 91, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 67, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 86, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 62, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 92, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 65, 23)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 87, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 60, 23)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 93, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 68, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 88, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 63, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 94, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 89, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 95, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 79, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 90, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 74, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 96, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 91, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 97, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 76, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 92, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 71, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 98, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 81, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 93, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 76, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 99, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 83, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 84, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 94, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 78, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 102, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 97, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 103, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 102, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 98, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 97, 3)) type Assert any> = T(); ->Assert : Symbol(Assert, Decl(typeCall.ts, 103, 20)) ->T : Symbol(T, Decl(typeCall.ts, 104, 12)) ->T : Symbol(T, Decl(typeCall.ts, 104, 12)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 98, 20)) +>T : Symbol(T, Decl(typeCall.ts, 99, 12)) +>T : Symbol(T, Decl(typeCall.ts, 99, 12)) let c1: Assert; ->c1 : Symbol(c1, Decl(typeCall.ts, 105, 3)) ->Assert : Symbol(Assert, Decl(typeCall.ts, 103, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 102, 3)) +>c1 : Symbol(c1, Decl(typeCall.ts, 100, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 98, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 97, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 105, 26)) ->T : Symbol(T, Decl(typeCall.ts, 107, 24)) ->x : Symbol(x, Decl(typeCall.ts, 107, 45)) ->T : Symbol(T, Decl(typeCall.ts, 107, 24)) ->T : Symbol(T, Decl(typeCall.ts, 107, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 100, 26)) +>T : Symbol(T, Decl(typeCall.ts, 102, 24)) +>x : Symbol(x, Decl(typeCall.ts, 102, 45)) +>T : Symbol(T, Decl(typeCall.ts, 102, 24)) +>T : Symbol(T, Decl(typeCall.ts, 102, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 105, 26)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 100, 26)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 108, 30)) ->T : Symbol(T, Decl(typeCall.ts, 110, 24)) ->x : Symbol(x, Decl(typeCall.ts, 110, 45)) ->a : Symbol(a, Decl(typeCall.ts, 110, 49)) ->T : Symbol(T, Decl(typeCall.ts, 110, 24)) ->T : Symbol(T, Decl(typeCall.ts, 110, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 103, 30)) +>T : Symbol(T, Decl(typeCall.ts, 105, 24)) +>x : Symbol(x, Decl(typeCall.ts, 105, 45)) +>a : Symbol(a, Decl(typeCall.ts, 105, 49)) +>T : Symbol(T, Decl(typeCall.ts, 105, 24)) +>T : Symbol(T, Decl(typeCall.ts, 105, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 108, 30)) ->a : Symbol(a, Decl(typeCall.ts, 111, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 103, 30)) +>a : Symbol(a, Decl(typeCall.ts, 106, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 111, 37)) ->T : Symbol(T, Decl(typeCall.ts, 113, 24)) ->x : Symbol(x, Decl(typeCall.ts, 113, 27)) ->a : Symbol(a, Decl(typeCall.ts, 113, 31)) ->T : Symbol(T, Decl(typeCall.ts, 113, 24)) ->T : Symbol(T, Decl(typeCall.ts, 113, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 106, 37)) +>T : Symbol(T, Decl(typeCall.ts, 108, 24)) +>x : Symbol(x, Decl(typeCall.ts, 108, 27)) +>a : Symbol(a, Decl(typeCall.ts, 108, 31)) +>T : Symbol(T, Decl(typeCall.ts, 108, 24)) +>T : Symbol(T, Decl(typeCall.ts, 108, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 111, 37)) ->a : Symbol(a, Decl(typeCall.ts, 114, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 106, 37)) +>a : Symbol(a, Decl(typeCall.ts, 109, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 115, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 111, 37)) ->a : Symbol(a, Decl(typeCall.ts, 115, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 110, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 106, 37)) +>a : Symbol(a, Decl(typeCall.ts, 110, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 115, 58)) ->T : Symbol(T, Decl(typeCall.ts, 117, 24)) ->x : Symbol(x, Decl(typeCall.ts, 117, 27)) ->T : Symbol(T, Decl(typeCall.ts, 117, 24)) ->y : Symbol(y, Decl(typeCall.ts, 117, 32)) ->T : Symbol(T, Decl(typeCall.ts, 117, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 110, 58)) +>T : Symbol(T, Decl(typeCall.ts, 112, 24)) +>x : Symbol(x, Decl(typeCall.ts, 112, 27)) +>T : Symbol(T, Decl(typeCall.ts, 112, 24)) +>y : Symbol(y, Decl(typeCall.ts, 112, 32)) +>T : Symbol(T, Decl(typeCall.ts, 112, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 115, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 110, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 118, 19)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) ->x : Symbol(x, Decl(typeCall.ts, 120, 26)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) ->y : Symbol(y, Decl(typeCall.ts, 120, 31)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 113, 19)) +>T : Symbol(T, Decl(typeCall.ts, 115, 23)) +>x : Symbol(x, Decl(typeCall.ts, 115, 26)) +>T : Symbol(T, Decl(typeCall.ts, 115, 23)) +>y : Symbol(y, Decl(typeCall.ts, 115, 31)) +>T : Symbol(T, Decl(typeCall.ts, 115, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 121, 9)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) ->x : Symbol(x, Decl(typeCall.ts, 120, 26)) +>a : Symbol(a, Decl(typeCall.ts, 116, 9)) +>T : Symbol(T, Decl(typeCall.ts, 115, 23)) +>x : Symbol(x, Decl(typeCall.ts, 115, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 122, 9)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) ->y : Symbol(y, Decl(typeCall.ts, 120, 31)) +>b : Symbol(b, Decl(typeCall.ts, 117, 9)) +>T : Symbol(T, Decl(typeCall.ts, 115, 23)) +>y : Symbol(y, Decl(typeCall.ts, 115, 31)) } function comparability(x: T, y: () => T) { ->comparability : Symbol(comparability, Decl(typeCall.ts, 123, 1)) ->T : Symbol(T, Decl(typeCall.ts, 125, 23)) ->x : Symbol(x, Decl(typeCall.ts, 125, 26)) ->T : Symbol(T, Decl(typeCall.ts, 125, 23)) ->y : Symbol(y, Decl(typeCall.ts, 125, 31)) ->T : Symbol(T, Decl(typeCall.ts, 125, 23)) +>comparability : Symbol(comparability, Decl(typeCall.ts, 118, 1)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>x : Symbol(x, Decl(typeCall.ts, 120, 26)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>y : Symbol(y, Decl(typeCall.ts, 120, 31)) +>T : Symbol(T, Decl(typeCall.ts, 120, 23)) x === x; ->x : Symbol(x, Decl(typeCall.ts, 125, 26)) ->x : Symbol(x, Decl(typeCall.ts, 125, 26)) +>x : Symbol(x, Decl(typeCall.ts, 120, 26)) +>x : Symbol(x, Decl(typeCall.ts, 120, 26)) y === y; ->y : Symbol(y, Decl(typeCall.ts, 125, 31)) ->y : Symbol(y, Decl(typeCall.ts, 125, 31)) +>y : Symbol(y, Decl(typeCall.ts, 120, 31)) +>y : Symbol(y, Decl(typeCall.ts, 120, 31)) // x === y; // rightfully errors } diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 2dd1ac5b77858..a68d405098adb 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -70,7 +70,7 @@ type Wrap = Id(T); >T : T type i = Wrap<123>; ->i : Id(T) +>i : 123 >Wrap : Id(T) type F5 = () => () => { a: () => 1; }; @@ -81,19 +81,6 @@ type j = F5()()['a'](); >j : 1 >F5 : F5 -declare function id(v: T): T; ->id : (v: T) => T ->T : T ->v : T ->T : T ->T : T - -let l = id('foo'); ->l : string ->id('foo') : string ->id : (v: T) => T ->'foo' : "foo" - interface IsPrimitive { >IsPrimitive : IsPrimitive @@ -103,11 +90,11 @@ interface IsPrimitive { (o: any): '1'; >o : any } -type stringIsPrimitive = IsPrimitive(string); // '1', ok +type stringIsPrimitive = IsPrimitive(string); >stringIsPrimitive : "1" >IsPrimitive : IsPrimitive -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +type regexpIsPrimitive = IsPrimitive(RegExp); >regexpIsPrimitive : "0" >IsPrimitive : IsPrimitive >RegExp : RegExp @@ -121,17 +108,15 @@ type genericIsPrimitive3 = (v: T) => IsPrimitive(T); >IsPrimitive : IsPrimitive >T : T -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok ->stringIsPrimitive3 : IsPrimitive(T) +type stringIsPrimitive3 = genericIsPrimitive3(string); +>stringIsPrimitive3 : "1" >genericIsPrimitive3 : genericIsPrimitive3 type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) ->regexpIsPrimitive3 : IsPrimitive(T) +>regexpIsPrimitive3 : "0" >genericIsPrimitive3 : genericIsPrimitive3 >RegExp : RegExp -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known - type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; >map : map >Fn : Fn @@ -152,7 +137,7 @@ type map = any, O extends { [k: string]: T }, T>(fn: Fn, o >P : P type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : { a: ((v: T) => [T])(O[P]); b: ((v: T) => [T])(O[P]); c: ((v: T) => [T])(O[P]); } +>z : { a: [1]; b: [2]; c: [3]; } >map : map >T : T >v : T @@ -162,8 +147,6 @@ type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >b : 2 >c : 3 -// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. - // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; >Fn1 : Fn1 @@ -213,16 +196,16 @@ let ones = null! as 1[]; >null : null type Fn4b = Fn3(typeof ones); ->Fn4b : Fn2(Fn1(T3)) +>Fn4b : ReadonlyArray<{}> >Fn3 : Fn3 >ones : 1[] -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); ->Fn4c : Fn2(Fn1(T3)) +>Fn4c : ReadonlyArray<{}> >Fn3 : Fn3 -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); diff --git a/tests/cases/compiler/overloadSelection.ts b/tests/cases/compiler/overloadSelection.ts index 06b5019fd53fb..2575dc5ac60c1 100644 --- a/tests/cases/compiler/overloadSelection.ts +++ b/tests/cases/compiler/overloadSelection.ts @@ -4,6 +4,5 @@ interface Match { (o: object): 0; (o: any): 1; } -type Wrap = (v: T) => Match(T); +type Wrap = (v: T) => Match(T); type A = Wrap(RegExp); -// falls thru to 1, `object` checked not with generic val `RegExp` but with its constraint (generic `any`) diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 56028983053b0..957cd144849f3 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -32,25 +32,20 @@ type i = Wrap<123>; type F5 = () => () => { a: () => 1; }; type j = F5()()['a'](); -declare function id(v: T): T; -let l = id('foo'); - interface IsPrimitive { (o: object): '0'; (o: any): '1'; } -type stringIsPrimitive = IsPrimitive(string); // '1', ok -type regexpIsPrimitive = IsPrimitive(RegExp); // '0', ok +type stringIsPrimitive = IsPrimitive(string); +type regexpIsPrimitive = IsPrimitive(RegExp); // alternative, pass as parameters type genericIsPrimitive3 = (v: T) => IsPrimitive(T); -type stringIsPrimitive3 = genericIsPrimitive3(string); // '1', ok +type stringIsPrimitive3 = genericIsPrimitive3(string); type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) -// fails, see #17471, '1' instead of '0', should delay overload selection until type argument is known type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -// FAILS!, wanted `{ a: [1], b: [2], c: [3] }`, got `{ a: any; b: any; c: any; }`. // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; @@ -61,9 +56,9 @@ type Fn3 = (v3: T3) => Fn2(Fn1(T3)); // type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; type Fn4b = Fn3(typeof ones); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray`. +// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); From c70ea67f43e25bd624c81e950febde2921eeb275 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 10 Sep 2017 00:27:01 +0800 Subject: [PATCH 14/25] factor out function --- src/compiler/checker.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c7a8c272b2af9..358bbf5651671 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7575,11 +7575,6 @@ namespace ts { return type; } - // overlap with typeToTypeNode? - function createTypeCallNodeFromType(type: TypeCallType): TypeCallTypeNode { - return createNodeBuilder().typeToTypeNode(type); - } - function getTypeCallType(fn: Type, args: Type[], node?: TypeCallTypeNode): Type { const type = createTypeCallType(fn, args); if (isGenericTypeCallType(fn) || some(args, isGenericTypeCallType)) { @@ -7588,7 +7583,7 @@ namespace ts { return getTypeFromTypeCall(type, node); } - function getTypeFromTypeCall(type: TypeCallType, node = createTypeCallNodeFromType(type)): Type { + function getTypeFromTypeCall(type: TypeCallType, node = nodeBuilder.typeToTypeNode(type)): Type { const fn = type.function; const args = type.arguments; const calls = getSignaturesOfType(fn, SignatureKind.Call); From f730a0720163604ddebce8610a1d39842cf1834b Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 10 Sep 2017 00:43:45 +0800 Subject: [PATCH 15/25] drop index type... not needed here unlike for gcnew's `!`? --- src/compiler/checker.ts | 4 ++-- src/compiler/types.ts | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 358bbf5651671..420257c0532f4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7524,7 +7524,7 @@ namespace ts { return links.resolvedType; } - function getIndexTypeForGenericType(type: TypeVariable | UnionOrIntersectionType | TypeCallType) { + function getIndexTypeForGenericType(type: TypeVariable | UnionOrIntersectionType) { if (!type.resolvedIndexType) { type.resolvedIndexType = createType(TypeFlags.Index); type.resolvedIndexType.type = type; @@ -7543,7 +7543,7 @@ namespace ts { } function getIndexType(type: Type): Type { - return maybeTypeOfKind(type, TypeFlags.TypeVariable) || isGenericTypeCallType(type) ? getIndexTypeForGenericType(type) : + return maybeTypeOfKind(type, TypeFlags.TypeVariable) || isGenericTypeCallType(type) ? getIndexTypeForGenericType(type) : getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(type) : type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromPropertyNames(type); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index cb423bc3bd112..ce31fb38274af 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3416,8 +3416,6 @@ namespace ts { export interface TypeCallType extends TypeVariable { function: Type; arguments: Type[]; - /* @internal */ - resolvedIndexType: IndexType; } // keyof T types (TypeFlags.Index) From 9bbae94bf2bff5a170c7904216017b82eaab454d Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 10 Sep 2017 00:54:29 +0800 Subject: [PATCH 16/25] add tests works: map, type checks. doesn't: compose, index check --- tests/baselines/reference/typeCall.js | 28 ++ tests/baselines/reference/typeCall.symbols | 371 ++++++++++++--------- tests/baselines/reference/typeCall.types | 69 ++++ tests/cases/compiler/typeCall.ts | 21 ++ 4 files changed, 337 insertions(+), 152 deletions(-) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index cc974244c08c3..29763c08d24ba 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -61,6 +61,27 @@ type Fn4c = Fn3(1[]); let y = fn2(fn1(ones)); type Y = Fn2(Fn1(1[])); +interface isT { + (v: never): '0'; + (v: T): '1'; + (v: any): '0'; +} +type Matches = isT(V); +type isBool = isT; +let falseBool: isBool(false); // 1 +let trueBool: isBool(true); // 1 +let strBool: isBool(string); // 0 +let anyBool: isBool(any); // 0 +let neverBool: isBool(never); // 0 + +interface ObjectHasStringIndex { + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; + (o: {}): '0'; +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. + type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; type CallMember any }, K extends keyof T> = T[K](); type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; @@ -159,6 +180,13 @@ var ones = null; // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok var y = fn2(fn1(ones)); +var falseBool; // 1 +var trueBool; // 1 +var strBool; // 0 +var anyBool; // 0 +var neverBool; // 0 +var ObjectHasStringIndexTestT; // '1' +var ObjectHasStringIndexTestF; // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. var a1; var b1; var c1; diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index c831b2d4486fc..09e4f2c609429 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -209,251 +209,318 @@ type Y = Fn2(Fn1(1[])); >Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) >Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) +interface isT { +>isT : Symbol(isT, Decl(typeCall.ts, 60, 23)) +>T : Symbol(T, Decl(typeCall.ts, 62, 14)) + + (v: never): '0'; +>v : Symbol(v, Decl(typeCall.ts, 63, 3)) + + (v: T): '1'; +>v : Symbol(v, Decl(typeCall.ts, 64, 3)) +>T : Symbol(T, Decl(typeCall.ts, 62, 14)) + + (v: any): '0'; +>v : Symbol(v, Decl(typeCall.ts, 65, 3)) +} +type Matches = isT(V); +>Matches : Symbol(Matches, Decl(typeCall.ts, 66, 1)) +>V : Symbol(V, Decl(typeCall.ts, 67, 13)) +>T : Symbol(T, Decl(typeCall.ts, 67, 15)) +>isT : Symbol(isT, Decl(typeCall.ts, 60, 23)) +>T : Symbol(T, Decl(typeCall.ts, 67, 15)) +>V : Symbol(V, Decl(typeCall.ts, 67, 13)) + +type isBool = isT; +>isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) +>isT : Symbol(isT, Decl(typeCall.ts, 60, 23)) + +let falseBool: isBool(false); // 1 +>falseBool : Symbol(falseBool, Decl(typeCall.ts, 69, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) + +let trueBool: isBool(true); // 1 +>trueBool : Symbol(trueBool, Decl(typeCall.ts, 70, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) + +let strBool: isBool(string); // 0 +>strBool : Symbol(strBool, Decl(typeCall.ts, 71, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) + +let anyBool: isBool(any); // 0 +>anyBool : Symbol(anyBool, Decl(typeCall.ts, 72, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) + +let neverBool: isBool(never); // 0 +>neverBool : Symbol(neverBool, Decl(typeCall.ts, 73, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) + +interface ObjectHasStringIndex { +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 73, 29)) + + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; +>o : Symbol(o, Decl(typeCall.ts, 77, 3)) +>k : Symbol(k, Decl(typeCall.ts, 77, 9)) + + (o: {}): '0'; +>o : Symbol(o, Decl(typeCall.ts, 78, 3)) +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +>ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 80, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 73, 29)) +>k : Symbol(k, Decl(typeCall.ts, 80, 55)) + +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. +>ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 81, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 73, 29)) +>a : Symbol(a, Decl(typeCall.ts, 81, 53)) + type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 60, 23)) ->T : Symbol(T, Decl(typeCall.ts, 62, 15)) ->k : Symbol(k, Decl(typeCall.ts, 62, 34)) ->K : Symbol(K, Decl(typeCall.ts, 62, 52)) ->T : Symbol(T, Decl(typeCall.ts, 62, 15)) ->T : Symbol(T, Decl(typeCall.ts, 62, 15)) ->K : Symbol(K, Decl(typeCall.ts, 62, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 81, 64)) +>T : Symbol(T, Decl(typeCall.ts, 83, 15)) +>k : Symbol(k, Decl(typeCall.ts, 83, 34)) +>K : Symbol(K, Decl(typeCall.ts, 83, 52)) +>T : Symbol(T, Decl(typeCall.ts, 83, 15)) +>T : Symbol(T, Decl(typeCall.ts, 83, 15)) +>K : Symbol(K, Decl(typeCall.ts, 83, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 62, 85)) ->T : Symbol(T, Decl(typeCall.ts, 63, 16)) ->k : Symbol(k, Decl(typeCall.ts, 63, 29)) ->K : Symbol(K, Decl(typeCall.ts, 63, 53)) ->T : Symbol(T, Decl(typeCall.ts, 63, 16)) ->T : Symbol(T, Decl(typeCall.ts, 63, 16)) ->K : Symbol(K, Decl(typeCall.ts, 63, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 83, 85)) +>T : Symbol(T, Decl(typeCall.ts, 84, 16)) +>k : Symbol(k, Decl(typeCall.ts, 84, 29)) +>K : Symbol(K, Decl(typeCall.ts, 84, 53)) +>T : Symbol(T, Decl(typeCall.ts, 84, 16)) +>T : Symbol(T, Decl(typeCall.ts, 84, 16)) +>K : Symbol(K, Decl(typeCall.ts, 84, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 63, 82)) ->T : Symbol(T, Decl(typeCall.ts, 64, 22)) ->k : Symbol(k, Decl(typeCall.ts, 64, 35)) ->K : Symbol(K, Decl(typeCall.ts, 64, 65)) ->T : Symbol(T, Decl(typeCall.ts, 64, 22)) ->T : Symbol(T, Decl(typeCall.ts, 64, 22)) ->K : Symbol(K, Decl(typeCall.ts, 64, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 84, 82)) +>T : Symbol(T, Decl(typeCall.ts, 85, 22)) +>k : Symbol(k, Decl(typeCall.ts, 85, 35)) +>K : Symbol(K, Decl(typeCall.ts, 85, 65)) +>T : Symbol(T, Decl(typeCall.ts, 85, 22)) +>T : Symbol(T, Decl(typeCall.ts, 85, 22)) +>K : Symbol(K, Decl(typeCall.ts, 85, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 64, 89)) ->T : Symbol(T, Decl(typeCall.ts, 66, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 66, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 85, 89)) +>T : Symbol(T, Decl(typeCall.ts, 87, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 87, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 67, 5)) ->T : Symbol(T, Decl(typeCall.ts, 66, 12)) +>K : Symbol(K, Decl(typeCall.ts, 88, 5)) +>T : Symbol(T, Decl(typeCall.ts, 87, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 68, 5)) +>key : Symbol(key, Decl(typeCall.ts, 89, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 66, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 87, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 69, 7)) ->T : Symbol(T, Decl(typeCall.ts, 71, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 64, 89)) ->T : Symbol(T, Decl(typeCall.ts, 71, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 90, 7)) +>T : Symbol(T, Decl(typeCall.ts, 92, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 85, 89)) +>T : Symbol(T, Decl(typeCall.ts, 92, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 71, 59)) ->T : Symbol(T, Decl(typeCall.ts, 72, 15)) ->k : Symbol(k, Decl(typeCall.ts, 72, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 72, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 92, 59)) +>T : Symbol(T, Decl(typeCall.ts, 93, 15)) +>k : Symbol(k, Decl(typeCall.ts, 93, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 93, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 73, 5)) ->T : Symbol(T, Decl(typeCall.ts, 72, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 64, 89)) ->T : Symbol(T, Decl(typeCall.ts, 72, 15)) ->K : Symbol(K, Decl(typeCall.ts, 73, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 72, 52)) +>K : Symbol(K, Decl(typeCall.ts, 94, 5)) +>T : Symbol(T, Decl(typeCall.ts, 93, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 85, 89)) +>T : Symbol(T, Decl(typeCall.ts, 93, 15)) +>K : Symbol(K, Decl(typeCall.ts, 94, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 93, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 74, 2)) ->T : Symbol(T, Decl(typeCall.ts, 76, 15)) ->T : Symbol(T, Decl(typeCall.ts, 76, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 95, 2)) +>T : Symbol(T, Decl(typeCall.ts, 97, 15)) +>T : Symbol(T, Decl(typeCall.ts, 97, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 76, 50)) ->T : Symbol(T, Decl(typeCall.ts, 78, 12)) ->K : Symbol(K, Decl(typeCall.ts, 78, 38)) ->T : Symbol(T, Decl(typeCall.ts, 78, 12)) ->T : Symbol(T, Decl(typeCall.ts, 78, 12)) ->K : Symbol(K, Decl(typeCall.ts, 78, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 97, 50)) +>T : Symbol(T, Decl(typeCall.ts, 99, 12)) +>K : Symbol(K, Decl(typeCall.ts, 99, 38)) +>T : Symbol(T, Decl(typeCall.ts, 99, 12)) +>T : Symbol(T, Decl(typeCall.ts, 99, 12)) +>K : Symbol(K, Decl(typeCall.ts, 99, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 78, 66)) ->T : Symbol(T, Decl(typeCall.ts, 79, 12)) ->k : Symbol(k, Decl(typeCall.ts, 79, 31)) ->K : Symbol(K, Decl(typeCall.ts, 79, 61)) ->T : Symbol(T, Decl(typeCall.ts, 79, 12)) ->T : Symbol(T, Decl(typeCall.ts, 79, 12)) ->K : Symbol(K, Decl(typeCall.ts, 79, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 99, 66)) +>T : Symbol(T, Decl(typeCall.ts, 100, 12)) +>k : Symbol(k, Decl(typeCall.ts, 100, 31)) +>K : Symbol(K, Decl(typeCall.ts, 100, 61)) +>T : Symbol(T, Decl(typeCall.ts, 100, 12)) +>T : Symbol(T, Decl(typeCall.ts, 100, 12)) +>K : Symbol(K, Decl(typeCall.ts, 100, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 81, 12)) +>x : Symbol(x, Decl(typeCall.ts, 102, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 82, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 83, 14)) ->value : Symbol(value, Decl(typeCall.ts, 83, 28)) +>z : Symbol(z, Decl(typeCall.ts, 103, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 104, 14)) +>value : Symbol(value, Decl(typeCall.ts, 104, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 84, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 105, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 86, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 62, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 107, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 83, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 87, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 60, 23)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 108, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 81, 64)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 88, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 63, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 109, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 84, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 89, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 110, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 90, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 74, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 111, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 95, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 91, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 112, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 92, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 71, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 113, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 92, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 93, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 76, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 114, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 97, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 94, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 78, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 79, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 115, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 99, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 97, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 118, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 98, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 97, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 119, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 118, 3)) type Assert any> = T(); ->Assert : Symbol(Assert, Decl(typeCall.ts, 98, 20)) ->T : Symbol(T, Decl(typeCall.ts, 99, 12)) ->T : Symbol(T, Decl(typeCall.ts, 99, 12)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 119, 20)) +>T : Symbol(T, Decl(typeCall.ts, 120, 12)) +>T : Symbol(T, Decl(typeCall.ts, 120, 12)) let c1: Assert; ->c1 : Symbol(c1, Decl(typeCall.ts, 100, 3)) ->Assert : Symbol(Assert, Decl(typeCall.ts, 98, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 97, 3)) +>c1 : Symbol(c1, Decl(typeCall.ts, 121, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 119, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 118, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 100, 26)) ->T : Symbol(T, Decl(typeCall.ts, 102, 24)) ->x : Symbol(x, Decl(typeCall.ts, 102, 45)) ->T : Symbol(T, Decl(typeCall.ts, 102, 24)) ->T : Symbol(T, Decl(typeCall.ts, 102, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 121, 26)) +>T : Symbol(T, Decl(typeCall.ts, 123, 24)) +>x : Symbol(x, Decl(typeCall.ts, 123, 45)) +>T : Symbol(T, Decl(typeCall.ts, 123, 24)) +>T : Symbol(T, Decl(typeCall.ts, 123, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 100, 26)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 121, 26)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 103, 30)) ->T : Symbol(T, Decl(typeCall.ts, 105, 24)) ->x : Symbol(x, Decl(typeCall.ts, 105, 45)) ->a : Symbol(a, Decl(typeCall.ts, 105, 49)) ->T : Symbol(T, Decl(typeCall.ts, 105, 24)) ->T : Symbol(T, Decl(typeCall.ts, 105, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 124, 30)) +>T : Symbol(T, Decl(typeCall.ts, 126, 24)) +>x : Symbol(x, Decl(typeCall.ts, 126, 45)) +>a : Symbol(a, Decl(typeCall.ts, 126, 49)) +>T : Symbol(T, Decl(typeCall.ts, 126, 24)) +>T : Symbol(T, Decl(typeCall.ts, 126, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 103, 30)) ->a : Symbol(a, Decl(typeCall.ts, 106, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 124, 30)) +>a : Symbol(a, Decl(typeCall.ts, 127, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 106, 37)) ->T : Symbol(T, Decl(typeCall.ts, 108, 24)) ->x : Symbol(x, Decl(typeCall.ts, 108, 27)) ->a : Symbol(a, Decl(typeCall.ts, 108, 31)) ->T : Symbol(T, Decl(typeCall.ts, 108, 24)) ->T : Symbol(T, Decl(typeCall.ts, 108, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 127, 37)) +>T : Symbol(T, Decl(typeCall.ts, 129, 24)) +>x : Symbol(x, Decl(typeCall.ts, 129, 27)) +>a : Symbol(a, Decl(typeCall.ts, 129, 31)) +>T : Symbol(T, Decl(typeCall.ts, 129, 24)) +>T : Symbol(T, Decl(typeCall.ts, 129, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 106, 37)) ->a : Symbol(a, Decl(typeCall.ts, 109, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 127, 37)) +>a : Symbol(a, Decl(typeCall.ts, 130, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 110, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 106, 37)) ->a : Symbol(a, Decl(typeCall.ts, 110, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 131, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 127, 37)) +>a : Symbol(a, Decl(typeCall.ts, 131, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 110, 58)) ->T : Symbol(T, Decl(typeCall.ts, 112, 24)) ->x : Symbol(x, Decl(typeCall.ts, 112, 27)) ->T : Symbol(T, Decl(typeCall.ts, 112, 24)) ->y : Symbol(y, Decl(typeCall.ts, 112, 32)) ->T : Symbol(T, Decl(typeCall.ts, 112, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 131, 58)) +>T : Symbol(T, Decl(typeCall.ts, 133, 24)) +>x : Symbol(x, Decl(typeCall.ts, 133, 27)) +>T : Symbol(T, Decl(typeCall.ts, 133, 24)) +>y : Symbol(y, Decl(typeCall.ts, 133, 32)) +>T : Symbol(T, Decl(typeCall.ts, 133, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 110, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 131, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 113, 19)) ->T : Symbol(T, Decl(typeCall.ts, 115, 23)) ->x : Symbol(x, Decl(typeCall.ts, 115, 26)) ->T : Symbol(T, Decl(typeCall.ts, 115, 23)) ->y : Symbol(y, Decl(typeCall.ts, 115, 31)) ->T : Symbol(T, Decl(typeCall.ts, 115, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 134, 19)) +>T : Symbol(T, Decl(typeCall.ts, 136, 23)) +>x : Symbol(x, Decl(typeCall.ts, 136, 26)) +>T : Symbol(T, Decl(typeCall.ts, 136, 23)) +>y : Symbol(y, Decl(typeCall.ts, 136, 31)) +>T : Symbol(T, Decl(typeCall.ts, 136, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 116, 9)) ->T : Symbol(T, Decl(typeCall.ts, 115, 23)) ->x : Symbol(x, Decl(typeCall.ts, 115, 26)) +>a : Symbol(a, Decl(typeCall.ts, 137, 9)) +>T : Symbol(T, Decl(typeCall.ts, 136, 23)) +>x : Symbol(x, Decl(typeCall.ts, 136, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 117, 9)) ->T : Symbol(T, Decl(typeCall.ts, 115, 23)) ->y : Symbol(y, Decl(typeCall.ts, 115, 31)) +>b : Symbol(b, Decl(typeCall.ts, 138, 9)) +>T : Symbol(T, Decl(typeCall.ts, 136, 23)) +>y : Symbol(y, Decl(typeCall.ts, 136, 31)) } function comparability(x: T, y: () => T) { ->comparability : Symbol(comparability, Decl(typeCall.ts, 118, 1)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) ->x : Symbol(x, Decl(typeCall.ts, 120, 26)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) ->y : Symbol(y, Decl(typeCall.ts, 120, 31)) ->T : Symbol(T, Decl(typeCall.ts, 120, 23)) +>comparability : Symbol(comparability, Decl(typeCall.ts, 139, 1)) +>T : Symbol(T, Decl(typeCall.ts, 141, 23)) +>x : Symbol(x, Decl(typeCall.ts, 141, 26)) +>T : Symbol(T, Decl(typeCall.ts, 141, 23)) +>y : Symbol(y, Decl(typeCall.ts, 141, 31)) +>T : Symbol(T, Decl(typeCall.ts, 141, 23)) x === x; ->x : Symbol(x, Decl(typeCall.ts, 120, 26)) ->x : Symbol(x, Decl(typeCall.ts, 120, 26)) +>x : Symbol(x, Decl(typeCall.ts, 141, 26)) +>x : Symbol(x, Decl(typeCall.ts, 141, 26)) y === y; ->y : Symbol(y, Decl(typeCall.ts, 120, 31)) ->y : Symbol(y, Decl(typeCall.ts, 120, 31)) +>y : Symbol(y, Decl(typeCall.ts, 141, 31)) +>y : Symbol(y, Decl(typeCall.ts, 141, 31)) // x === y; // rightfully errors } diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index a68d405098adb..3cbfa101ceb9a 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -221,6 +221,75 @@ type Y = Fn2(Fn1(1[])); >Fn2 : Fn2 >Fn1 : Fn1 +interface isT { +>isT : isT +>T : T + + (v: never): '0'; +>v : never + + (v: T): '1'; +>v : T +>T : T + + (v: any): '0'; +>v : any +} +type Matches = isT(V); +>Matches : isT(V) +>V : V +>T : T +>isT : isT +>T : T +>V : V + +type isBool = isT; +>isBool : isT +>isT : isT + +let falseBool: isBool(false); // 1 +>falseBool : "1" +>isBool : isT +>false : false + +let trueBool: isBool(true); // 1 +>trueBool : "1" +>isBool : isT +>true : true + +let strBool: isBool(string); // 0 +>strBool : "0" +>isBool : isT + +let anyBool: isBool(any); // 0 +>anyBool : "0" +>isBool : isT + +let neverBool: isBool(never); // 0 +>neverBool : "0" +>isBool : isT + +interface ObjectHasStringIndex { +>ObjectHasStringIndex : ObjectHasStringIndex + + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; +>o : { [k: string]: any; } +>k : string + + (o: {}): '0'; +>o : {} +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +>ObjectHasStringIndexTestT : "1" +>ObjectHasStringIndex : ObjectHasStringIndex +>k : string + +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. +>ObjectHasStringIndexTestF : "1" +>ObjectHasStringIndex : ObjectHasStringIndex +>a : 123 + type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; >IndexCall : T()[K] >T : T diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 957cd144849f3..ae0fb791b70a4 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -64,6 +64,27 @@ type Fn4c = Fn3(1[]); let y = fn2(fn1(ones)); type Y = Fn2(Fn1(1[])); +interface isT { + (v: never): '0'; + (v: T): '1'; + (v: any): '0'; +} +type Matches = isT(V); +type isBool = isT; +let falseBool: isBool(false); // 1 +let trueBool: isBool(true); // 1 +let strBool: isBool(string); // 0 +let anyBool: isBool(any); // 0 +let neverBool: isBool(never); // 0 + +interface ObjectHasStringIndex { + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; + (o: {}): '0'; +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. + type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; type CallMember any }, K extends keyof T> = T[K](); type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; From 28aece041f22d0777d4968648959229f09fe9ee8 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 10 Sep 2017 01:51:19 +0800 Subject: [PATCH 17/25] tests: reduce/map WIP --- tests/baselines/reference/typeCall.js | 36 ++ tests/baselines/reference/typeCall.symbols | 563 +++++++++++++-------- tests/baselines/reference/typeCall.types | 122 +++++ tests/cases/compiler/typeCall.ts | 33 ++ 4 files changed, 530 insertions(+), 224 deletions(-) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 29763c08d24ba..7ee4930dac778 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -43,6 +43,39 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); +// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +type PathFn, I extends string = '0'> = + { 1: PathFn, 0: T }[TupleHasIndex]; +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +declare function path>(obj: T, path: R): PathFn; +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +const keys = null! as ['a', 'b', '1', 'd']; +const pathTest = path(obj, keys); +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; @@ -172,6 +205,9 @@ function comparability(x: T, y: () => T) { //// [typeCall.js] var a = 'foo'; +var obj = null; +var keys = null; +var pathTest = path(obj, keys); var fn1 = null; var fn2 = null; // type Fn4 = Fn3(1); // errors, ok diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 09e4f2c609429..242c1b773f2bb 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -117,7 +117,7 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; ->map : Symbol(map, Decl(typeCall.ts, 40, 53)) +>map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) >Fn : Symbol(Fn, Decl(typeCall.ts, 42, 12)) >v : Symbol(v, Decl(typeCall.ts, 42, 24)) >T : Symbol(T, Decl(typeCall.ts, 42, 67)) @@ -137,7 +137,7 @@ type map = any, O extends { [k: string]: T }, T>(fn: Fn, o type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >z : Symbol(z, Decl(typeCall.ts, 42, 119)) ->map : Symbol(map, Decl(typeCall.ts, 40, 53)) +>map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) >T : Symbol(T, Decl(typeCall.ts, 43, 14)) >v : Symbol(v, Decl(typeCall.ts, 43, 17)) >T : Symbol(T, Decl(typeCall.ts, 43, 14)) @@ -146,381 +146,496 @@ type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >b : Symbol(b, Decl(typeCall.ts, 43, 38)) >c : Symbol(c, Decl(typeCall.ts, 43, 44)) +declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); +>map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 44, 21)) +>v : Symbol(v, Decl(typeCall.ts, 44, 33)) +>T : Symbol(T, Decl(typeCall.ts, 44, 76)) +>O : Symbol(O, Decl(typeCall.ts, 44, 46)) +>k : Symbol(k, Decl(typeCall.ts, 44, 60)) +>T : Symbol(T, Decl(typeCall.ts, 44, 76)) +>T : Symbol(T, Decl(typeCall.ts, 44, 76)) +>fn : Symbol(fn, Decl(typeCall.ts, 44, 80)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 44, 21)) +>obj : Symbol(obj, Decl(typeCall.ts, 44, 87)) +>O : Symbol(O, Decl(typeCall.ts, 44, 46)) +>map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 44, 21)) +>O : Symbol(O, Decl(typeCall.ts, 44, 46)) + +// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +>Inc : Symbol(Inc, Decl(typeCall.ts, 44, 108)) +>k : Symbol(k, Decl(typeCall.ts, 48, 14)) + +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 48, 98)) +>k : Symbol(k, Decl(typeCall.ts, 49, 25)) + +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 49, 82)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 50, 19)) +>I : Symbol(I, Decl(typeCall.ts, 50, 37)) +>K : Symbol(K, Decl(typeCall.ts, 50, 61)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 50, 19)) +>k : Symbol(k, Decl(typeCall.ts, 50, 89)) +>I : Symbol(I, Decl(typeCall.ts, 50, 37)) + +type PathFn, I extends string = '0'> = +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) +>T : Symbol(T, Decl(typeCall.ts, 51, 12)) +>k : Symbol(k, Decl(typeCall.ts, 51, 25)) +>R : Symbol(R, Decl(typeCall.ts, 51, 43)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>I : Symbol(I, Decl(typeCall.ts, 51, 68)) + + { 1: PathFn, 0: T }[TupleHasIndex]; +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) +>T : Symbol(T, Decl(typeCall.ts, 51, 12)) +>R : Symbol(R, Decl(typeCall.ts, 51, 43)) +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 48, 98)) +>I : Symbol(I, Decl(typeCall.ts, 51, 68)) +>R : Symbol(R, Decl(typeCall.ts, 51, 43)) +>Inc : Symbol(Inc, Decl(typeCall.ts, 44, 108)) +>I : Symbol(I, Decl(typeCall.ts, 51, 68)) +>T : Symbol(T, Decl(typeCall.ts, 51, 12)) +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 49, 82)) +>R : Symbol(R, Decl(typeCall.ts, 51, 43)) +>I : Symbol(I, Decl(typeCall.ts, 51, 68)) + +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +>PathTest : Symbol(PathTest, Decl(typeCall.ts, 52, 81)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) +>a : Symbol(a, Decl(typeCall.ts, 53, 24)) +>b : Symbol(b, Decl(typeCall.ts, 53, 29)) +>d : Symbol(d, Decl(typeCall.ts, 53, 40)) + +declare function path>(obj: T, path: R): PathFn; +>path : Symbol(path, Decl(typeCall.ts, 53, 78)) +>T : Symbol(T, Decl(typeCall.ts, 54, 22)) +>k : Symbol(k, Decl(typeCall.ts, 54, 35)) +>R : Symbol(R, Decl(typeCall.ts, 54, 53)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>obj : Symbol(obj, Decl(typeCall.ts, 54, 79)) +>T : Symbol(T, Decl(typeCall.ts, 54, 22)) +>path : Symbol(path, Decl(typeCall.ts, 54, 86)) +>R : Symbol(R, Decl(typeCall.ts, 54, 53)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) +>T : Symbol(T, Decl(typeCall.ts, 54, 22)) +>R : Symbol(R, Decl(typeCall.ts, 54, 53)) + +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +>obj : Symbol(obj, Decl(typeCall.ts, 55, 5)) +>a : Symbol(a, Decl(typeCall.ts, 55, 22)) +>b : Symbol(b, Decl(typeCall.ts, 55, 27)) +>d : Symbol(d, Decl(typeCall.ts, 55, 38)) + +const keys = null! as ['a', 'b', '1', 'd']; +>keys : Symbol(keys, Decl(typeCall.ts, 56, 5)) + +const pathTest = path(obj, keys); +>pathTest : Symbol(pathTest, Decl(typeCall.ts, 57, 5)) +>path : Symbol(path, Decl(typeCall.ts, 53, 78)) +>obj : Symbol(obj, Decl(typeCall.ts, 55, 5)) +>keys : Symbol(keys, Decl(typeCall.ts, 56, 5)) + +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" + // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) ->T1 : Symbol(T1, Decl(typeCall.ts, 46, 12)) ->v1 : Symbol(v1, Decl(typeCall.ts, 46, 31)) ->T1 : Symbol(T1, Decl(typeCall.ts, 46, 12)) ->k : Symbol(k, Decl(typeCall.ts, 46, 47)) ->T1 : Symbol(T1, Decl(typeCall.ts, 46, 12)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) +>T1 : Symbol(T1, Decl(typeCall.ts, 79, 12)) +>v1 : Symbol(v1, Decl(typeCall.ts, 79, 31)) +>T1 : Symbol(T1, Decl(typeCall.ts, 79, 12)) +>k : Symbol(k, Decl(typeCall.ts, 79, 47)) +>T1 : Symbol(T1, Decl(typeCall.ts, 79, 12)) type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) ->T2 : Symbol(T2, Decl(typeCall.ts, 47, 12)) ->v2 : Symbol(v2, Decl(typeCall.ts, 47, 16)) ->k : Symbol(k, Decl(typeCall.ts, 47, 23)) ->T2 : Symbol(T2, Decl(typeCall.ts, 47, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) +>T2 : Symbol(T2, Decl(typeCall.ts, 80, 12)) +>v2 : Symbol(v2, Decl(typeCall.ts, 80, 16)) +>k : Symbol(k, Decl(typeCall.ts, 80, 23)) +>T2 : Symbol(T2, Decl(typeCall.ts, 80, 12)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) ->T2 : Symbol(T2, Decl(typeCall.ts, 47, 12)) +>T2 : Symbol(T2, Decl(typeCall.ts, 80, 12)) let fn1 = null! as Fn1; ->fn1 : Symbol(fn1, Decl(typeCall.ts, 48, 3)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 81, 3)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) let fn2 = null! as Fn2; ->fn2 : Symbol(fn2, Decl(typeCall.ts, 49, 3)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 82, 3)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) type Fn3 = (v3: T3) => Fn2(Fn1(T3)); ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 49, 23)) ->T3 : Symbol(T3, Decl(typeCall.ts, 50, 12)) ->v3 : Symbol(v3, Decl(typeCall.ts, 50, 33)) ->T3 : Symbol(T3, Decl(typeCall.ts, 50, 12)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) ->T3 : Symbol(T3, Decl(typeCall.ts, 50, 12)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 82, 23)) +>T3 : Symbol(T3, Decl(typeCall.ts, 83, 12)) +>v3 : Symbol(v3, Decl(typeCall.ts, 83, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 83, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 83, 12)) // type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; ->ones : Symbol(ones, Decl(typeCall.ts, 52, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 85, 3)) type Fn4b = Fn3(typeof ones); ->Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 52, 24)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 49, 23)) ->ones : Symbol(ones, Decl(typeCall.ts, 52, 3)) +>Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 85, 24)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 82, 23)) +>ones : Symbol(ones, Decl(typeCall.ts, 85, 3)) // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); ->Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 53, 29)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 49, 23)) +>Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 86, 29)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 82, 23)) // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. // let x = fn2(fn1(1)); // errors with not assignable, ok // type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); ->y : Symbol(y, Decl(typeCall.ts, 59, 3)) ->fn2 : Symbol(fn2, Decl(typeCall.ts, 49, 3)) ->fn1 : Symbol(fn1, Decl(typeCall.ts, 48, 3)) ->ones : Symbol(ones, Decl(typeCall.ts, 52, 3)) +>y : Symbol(y, Decl(typeCall.ts, 92, 3)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 82, 3)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 81, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 85, 3)) type Y = Fn2(Fn1(1[])); ->Y : Symbol(Y, Decl(typeCall.ts, 59, 23)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 46, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 43, 53)) +>Y : Symbol(Y, Decl(typeCall.ts, 92, 23)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) interface isT { ->isT : Symbol(isT, Decl(typeCall.ts, 60, 23)) ->T : Symbol(T, Decl(typeCall.ts, 62, 14)) +>isT : Symbol(isT, Decl(typeCall.ts, 93, 23)) +>T : Symbol(T, Decl(typeCall.ts, 95, 14)) (v: never): '0'; ->v : Symbol(v, Decl(typeCall.ts, 63, 3)) +>v : Symbol(v, Decl(typeCall.ts, 96, 3)) (v: T): '1'; ->v : Symbol(v, Decl(typeCall.ts, 64, 3)) ->T : Symbol(T, Decl(typeCall.ts, 62, 14)) +>v : Symbol(v, Decl(typeCall.ts, 97, 3)) +>T : Symbol(T, Decl(typeCall.ts, 95, 14)) (v: any): '0'; ->v : Symbol(v, Decl(typeCall.ts, 65, 3)) +>v : Symbol(v, Decl(typeCall.ts, 98, 3)) } type Matches = isT(V); ->Matches : Symbol(Matches, Decl(typeCall.ts, 66, 1)) ->V : Symbol(V, Decl(typeCall.ts, 67, 13)) ->T : Symbol(T, Decl(typeCall.ts, 67, 15)) ->isT : Symbol(isT, Decl(typeCall.ts, 60, 23)) ->T : Symbol(T, Decl(typeCall.ts, 67, 15)) ->V : Symbol(V, Decl(typeCall.ts, 67, 13)) +>Matches : Symbol(Matches, Decl(typeCall.ts, 99, 1)) +>V : Symbol(V, Decl(typeCall.ts, 100, 13)) +>T : Symbol(T, Decl(typeCall.ts, 100, 15)) +>isT : Symbol(isT, Decl(typeCall.ts, 93, 23)) +>T : Symbol(T, Decl(typeCall.ts, 100, 15)) +>V : Symbol(V, Decl(typeCall.ts, 100, 13)) type isBool = isT; ->isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) ->isT : Symbol(isT, Decl(typeCall.ts, 60, 23)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) +>isT : Symbol(isT, Decl(typeCall.ts, 93, 23)) let falseBool: isBool(false); // 1 ->falseBool : Symbol(falseBool, Decl(typeCall.ts, 69, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) +>falseBool : Symbol(falseBool, Decl(typeCall.ts, 102, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) let trueBool: isBool(true); // 1 ->trueBool : Symbol(trueBool, Decl(typeCall.ts, 70, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) +>trueBool : Symbol(trueBool, Decl(typeCall.ts, 103, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) let strBool: isBool(string); // 0 ->strBool : Symbol(strBool, Decl(typeCall.ts, 71, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) +>strBool : Symbol(strBool, Decl(typeCall.ts, 104, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) let anyBool: isBool(any); // 0 ->anyBool : Symbol(anyBool, Decl(typeCall.ts, 72, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) +>anyBool : Symbol(anyBool, Decl(typeCall.ts, 105, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) let neverBool: isBool(never); // 0 ->neverBool : Symbol(neverBool, Decl(typeCall.ts, 73, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 67, 31)) +>neverBool : Symbol(neverBool, Decl(typeCall.ts, 106, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) interface ObjectHasStringIndex { ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 73, 29)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 106, 29)) // (o: T): T[string]; (o: { [k: string]: any }): '1'; ->o : Symbol(o, Decl(typeCall.ts, 77, 3)) ->k : Symbol(k, Decl(typeCall.ts, 77, 9)) +>o : Symbol(o, Decl(typeCall.ts, 110, 3)) +>k : Symbol(k, Decl(typeCall.ts, 110, 9)) (o: {}): '0'; ->o : Symbol(o, Decl(typeCall.ts, 78, 3)) +>o : Symbol(o, Decl(typeCall.ts, 111, 3)) } let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' ->ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 80, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 73, 29)) ->k : Symbol(k, Decl(typeCall.ts, 80, 55)) +>ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 113, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 106, 29)) +>k : Symbol(k, Decl(typeCall.ts, 113, 55)) let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. ->ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 81, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 73, 29)) ->a : Symbol(a, Decl(typeCall.ts, 81, 53)) +>ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 114, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 106, 29)) +>a : Symbol(a, Decl(typeCall.ts, 114, 53)) type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 81, 64)) ->T : Symbol(T, Decl(typeCall.ts, 83, 15)) ->k : Symbol(k, Decl(typeCall.ts, 83, 34)) ->K : Symbol(K, Decl(typeCall.ts, 83, 52)) ->T : Symbol(T, Decl(typeCall.ts, 83, 15)) ->T : Symbol(T, Decl(typeCall.ts, 83, 15)) ->K : Symbol(K, Decl(typeCall.ts, 83, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 114, 64)) +>T : Symbol(T, Decl(typeCall.ts, 116, 15)) +>k : Symbol(k, Decl(typeCall.ts, 116, 34)) +>K : Symbol(K, Decl(typeCall.ts, 116, 52)) +>T : Symbol(T, Decl(typeCall.ts, 116, 15)) +>T : Symbol(T, Decl(typeCall.ts, 116, 15)) +>K : Symbol(K, Decl(typeCall.ts, 116, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 83, 85)) ->T : Symbol(T, Decl(typeCall.ts, 84, 16)) ->k : Symbol(k, Decl(typeCall.ts, 84, 29)) ->K : Symbol(K, Decl(typeCall.ts, 84, 53)) ->T : Symbol(T, Decl(typeCall.ts, 84, 16)) ->T : Symbol(T, Decl(typeCall.ts, 84, 16)) ->K : Symbol(K, Decl(typeCall.ts, 84, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 116, 85)) +>T : Symbol(T, Decl(typeCall.ts, 117, 16)) +>k : Symbol(k, Decl(typeCall.ts, 117, 29)) +>K : Symbol(K, Decl(typeCall.ts, 117, 53)) +>T : Symbol(T, Decl(typeCall.ts, 117, 16)) +>T : Symbol(T, Decl(typeCall.ts, 117, 16)) +>K : Symbol(K, Decl(typeCall.ts, 117, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 84, 82)) ->T : Symbol(T, Decl(typeCall.ts, 85, 22)) ->k : Symbol(k, Decl(typeCall.ts, 85, 35)) ->K : Symbol(K, Decl(typeCall.ts, 85, 65)) ->T : Symbol(T, Decl(typeCall.ts, 85, 22)) ->T : Symbol(T, Decl(typeCall.ts, 85, 22)) ->K : Symbol(K, Decl(typeCall.ts, 85, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 117, 82)) +>T : Symbol(T, Decl(typeCall.ts, 118, 22)) +>k : Symbol(k, Decl(typeCall.ts, 118, 35)) +>K : Symbol(K, Decl(typeCall.ts, 118, 65)) +>T : Symbol(T, Decl(typeCall.ts, 118, 22)) +>T : Symbol(T, Decl(typeCall.ts, 118, 22)) +>K : Symbol(K, Decl(typeCall.ts, 118, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 85, 89)) ->T : Symbol(T, Decl(typeCall.ts, 87, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 87, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 118, 89)) +>T : Symbol(T, Decl(typeCall.ts, 120, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 120, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 88, 5)) ->T : Symbol(T, Decl(typeCall.ts, 87, 12)) +>K : Symbol(K, Decl(typeCall.ts, 121, 5)) +>T : Symbol(T, Decl(typeCall.ts, 120, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 89, 5)) +>key : Symbol(key, Decl(typeCall.ts, 122, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 87, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 120, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 90, 7)) ->T : Symbol(T, Decl(typeCall.ts, 92, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 85, 89)) ->T : Symbol(T, Decl(typeCall.ts, 92, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 123, 7)) +>T : Symbol(T, Decl(typeCall.ts, 125, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 118, 89)) +>T : Symbol(T, Decl(typeCall.ts, 125, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 92, 59)) ->T : Symbol(T, Decl(typeCall.ts, 93, 15)) ->k : Symbol(k, Decl(typeCall.ts, 93, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 93, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 125, 59)) +>T : Symbol(T, Decl(typeCall.ts, 126, 15)) +>k : Symbol(k, Decl(typeCall.ts, 126, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 126, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 94, 5)) ->T : Symbol(T, Decl(typeCall.ts, 93, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 85, 89)) ->T : Symbol(T, Decl(typeCall.ts, 93, 15)) ->K : Symbol(K, Decl(typeCall.ts, 94, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 93, 52)) +>K : Symbol(K, Decl(typeCall.ts, 127, 5)) +>T : Symbol(T, Decl(typeCall.ts, 126, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 118, 89)) +>T : Symbol(T, Decl(typeCall.ts, 126, 15)) +>K : Symbol(K, Decl(typeCall.ts, 127, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 126, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 95, 2)) ->T : Symbol(T, Decl(typeCall.ts, 97, 15)) ->T : Symbol(T, Decl(typeCall.ts, 97, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 128, 2)) +>T : Symbol(T, Decl(typeCall.ts, 130, 15)) +>T : Symbol(T, Decl(typeCall.ts, 130, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 97, 50)) ->T : Symbol(T, Decl(typeCall.ts, 99, 12)) ->K : Symbol(K, Decl(typeCall.ts, 99, 38)) ->T : Symbol(T, Decl(typeCall.ts, 99, 12)) ->T : Symbol(T, Decl(typeCall.ts, 99, 12)) ->K : Symbol(K, Decl(typeCall.ts, 99, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 130, 50)) +>T : Symbol(T, Decl(typeCall.ts, 132, 12)) +>K : Symbol(K, Decl(typeCall.ts, 132, 38)) +>T : Symbol(T, Decl(typeCall.ts, 132, 12)) +>T : Symbol(T, Decl(typeCall.ts, 132, 12)) +>K : Symbol(K, Decl(typeCall.ts, 132, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 99, 66)) ->T : Symbol(T, Decl(typeCall.ts, 100, 12)) ->k : Symbol(k, Decl(typeCall.ts, 100, 31)) ->K : Symbol(K, Decl(typeCall.ts, 100, 61)) ->T : Symbol(T, Decl(typeCall.ts, 100, 12)) ->T : Symbol(T, Decl(typeCall.ts, 100, 12)) ->K : Symbol(K, Decl(typeCall.ts, 100, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 132, 66)) +>T : Symbol(T, Decl(typeCall.ts, 133, 12)) +>k : Symbol(k, Decl(typeCall.ts, 133, 31)) +>K : Symbol(K, Decl(typeCall.ts, 133, 61)) +>T : Symbol(T, Decl(typeCall.ts, 133, 12)) +>T : Symbol(T, Decl(typeCall.ts, 133, 12)) +>K : Symbol(K, Decl(typeCall.ts, 133, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 102, 12)) +>x : Symbol(x, Decl(typeCall.ts, 135, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 103, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 104, 14)) ->value : Symbol(value, Decl(typeCall.ts, 104, 28)) +>z : Symbol(z, Decl(typeCall.ts, 136, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 137, 14)) +>value : Symbol(value, Decl(typeCall.ts, 137, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 105, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 138, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 107, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 83, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 140, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 116, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 108, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 81, 64)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 141, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 114, 64)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 109, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 84, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 142, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 117, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 110, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 143, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 111, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 95, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 144, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 128, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 112, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 145, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 113, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 92, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 146, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 125, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 114, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 97, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 147, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 130, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 115, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 99, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 100, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 148, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 132, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 118, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 151, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 119, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 118, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 152, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 151, 3)) type Assert any> = T(); ->Assert : Symbol(Assert, Decl(typeCall.ts, 119, 20)) ->T : Symbol(T, Decl(typeCall.ts, 120, 12)) ->T : Symbol(T, Decl(typeCall.ts, 120, 12)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 152, 20)) +>T : Symbol(T, Decl(typeCall.ts, 153, 12)) +>T : Symbol(T, Decl(typeCall.ts, 153, 12)) let c1: Assert; ->c1 : Symbol(c1, Decl(typeCall.ts, 121, 3)) ->Assert : Symbol(Assert, Decl(typeCall.ts, 119, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 118, 3)) +>c1 : Symbol(c1, Decl(typeCall.ts, 154, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 152, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 151, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 121, 26)) ->T : Symbol(T, Decl(typeCall.ts, 123, 24)) ->x : Symbol(x, Decl(typeCall.ts, 123, 45)) ->T : Symbol(T, Decl(typeCall.ts, 123, 24)) ->T : Symbol(T, Decl(typeCall.ts, 123, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 154, 26)) +>T : Symbol(T, Decl(typeCall.ts, 156, 24)) +>x : Symbol(x, Decl(typeCall.ts, 156, 45)) +>T : Symbol(T, Decl(typeCall.ts, 156, 24)) +>T : Symbol(T, Decl(typeCall.ts, 156, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 121, 26)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 154, 26)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 124, 30)) ->T : Symbol(T, Decl(typeCall.ts, 126, 24)) ->x : Symbol(x, Decl(typeCall.ts, 126, 45)) ->a : Symbol(a, Decl(typeCall.ts, 126, 49)) ->T : Symbol(T, Decl(typeCall.ts, 126, 24)) ->T : Symbol(T, Decl(typeCall.ts, 126, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 157, 30)) +>T : Symbol(T, Decl(typeCall.ts, 159, 24)) +>x : Symbol(x, Decl(typeCall.ts, 159, 45)) +>a : Symbol(a, Decl(typeCall.ts, 159, 49)) +>T : Symbol(T, Decl(typeCall.ts, 159, 24)) +>T : Symbol(T, Decl(typeCall.ts, 159, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 124, 30)) ->a : Symbol(a, Decl(typeCall.ts, 127, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 157, 30)) +>a : Symbol(a, Decl(typeCall.ts, 160, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 127, 37)) ->T : Symbol(T, Decl(typeCall.ts, 129, 24)) ->x : Symbol(x, Decl(typeCall.ts, 129, 27)) ->a : Symbol(a, Decl(typeCall.ts, 129, 31)) ->T : Symbol(T, Decl(typeCall.ts, 129, 24)) ->T : Symbol(T, Decl(typeCall.ts, 129, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 160, 37)) +>T : Symbol(T, Decl(typeCall.ts, 162, 24)) +>x : Symbol(x, Decl(typeCall.ts, 162, 27)) +>a : Symbol(a, Decl(typeCall.ts, 162, 31)) +>T : Symbol(T, Decl(typeCall.ts, 162, 24)) +>T : Symbol(T, Decl(typeCall.ts, 162, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 127, 37)) ->a : Symbol(a, Decl(typeCall.ts, 130, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 160, 37)) +>a : Symbol(a, Decl(typeCall.ts, 163, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 131, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 127, 37)) ->a : Symbol(a, Decl(typeCall.ts, 131, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 164, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 160, 37)) +>a : Symbol(a, Decl(typeCall.ts, 164, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 131, 58)) ->T : Symbol(T, Decl(typeCall.ts, 133, 24)) ->x : Symbol(x, Decl(typeCall.ts, 133, 27)) ->T : Symbol(T, Decl(typeCall.ts, 133, 24)) ->y : Symbol(y, Decl(typeCall.ts, 133, 32)) ->T : Symbol(T, Decl(typeCall.ts, 133, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 164, 58)) +>T : Symbol(T, Decl(typeCall.ts, 166, 24)) +>x : Symbol(x, Decl(typeCall.ts, 166, 27)) +>T : Symbol(T, Decl(typeCall.ts, 166, 24)) +>y : Symbol(y, Decl(typeCall.ts, 166, 32)) +>T : Symbol(T, Decl(typeCall.ts, 166, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 131, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 164, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 134, 19)) ->T : Symbol(T, Decl(typeCall.ts, 136, 23)) ->x : Symbol(x, Decl(typeCall.ts, 136, 26)) ->T : Symbol(T, Decl(typeCall.ts, 136, 23)) ->y : Symbol(y, Decl(typeCall.ts, 136, 31)) ->T : Symbol(T, Decl(typeCall.ts, 136, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 167, 19)) +>T : Symbol(T, Decl(typeCall.ts, 169, 23)) +>x : Symbol(x, Decl(typeCall.ts, 169, 26)) +>T : Symbol(T, Decl(typeCall.ts, 169, 23)) +>y : Symbol(y, Decl(typeCall.ts, 169, 31)) +>T : Symbol(T, Decl(typeCall.ts, 169, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 137, 9)) ->T : Symbol(T, Decl(typeCall.ts, 136, 23)) ->x : Symbol(x, Decl(typeCall.ts, 136, 26)) +>a : Symbol(a, Decl(typeCall.ts, 170, 9)) +>T : Symbol(T, Decl(typeCall.ts, 169, 23)) +>x : Symbol(x, Decl(typeCall.ts, 169, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 138, 9)) ->T : Symbol(T, Decl(typeCall.ts, 136, 23)) ->y : Symbol(y, Decl(typeCall.ts, 136, 31)) +>b : Symbol(b, Decl(typeCall.ts, 171, 9)) +>T : Symbol(T, Decl(typeCall.ts, 169, 23)) +>y : Symbol(y, Decl(typeCall.ts, 169, 31)) } function comparability(x: T, y: () => T) { ->comparability : Symbol(comparability, Decl(typeCall.ts, 139, 1)) ->T : Symbol(T, Decl(typeCall.ts, 141, 23)) ->x : Symbol(x, Decl(typeCall.ts, 141, 26)) ->T : Symbol(T, Decl(typeCall.ts, 141, 23)) ->y : Symbol(y, Decl(typeCall.ts, 141, 31)) ->T : Symbol(T, Decl(typeCall.ts, 141, 23)) +>comparability : Symbol(comparability, Decl(typeCall.ts, 172, 1)) +>T : Symbol(T, Decl(typeCall.ts, 174, 23)) +>x : Symbol(x, Decl(typeCall.ts, 174, 26)) +>T : Symbol(T, Decl(typeCall.ts, 174, 23)) +>y : Symbol(y, Decl(typeCall.ts, 174, 31)) +>T : Symbol(T, Decl(typeCall.ts, 174, 23)) x === x; ->x : Symbol(x, Decl(typeCall.ts, 141, 26)) ->x : Symbol(x, Decl(typeCall.ts, 141, 26)) +>x : Symbol(x, Decl(typeCall.ts, 174, 26)) +>x : Symbol(x, Decl(typeCall.ts, 174, 26)) y === y; ->y : Symbol(y, Decl(typeCall.ts, 141, 31)) ->y : Symbol(y, Decl(typeCall.ts, 141, 31)) +>y : Symbol(y, Decl(typeCall.ts, 174, 31)) +>y : Symbol(y, Decl(typeCall.ts, 174, 31)) // x === y; // rightfully errors } diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 3cbfa101ceb9a..7957d07812de3 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -147,6 +147,128 @@ type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >b : 2 >c : 3 +declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); +>map : any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => map(Fn, O) +>Fn : Fn +>v : T +>T : T +>O : O +>k : string +>T : T +>T : T +>fn : Fn +>Fn : Fn +>obj : O +>O : O +>map : map +>Fn : Fn +>O : O + +// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +>Inc : Inc +>k : string + +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +>StringToNumber : StringToNumber +>k : string + +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +>TupleHasIndex : ({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I] +>Arr : Arr +>I : I +>K : K +>Arr : Arr +>k : string +>I : I + +type PathFn, I extends string = '0'> = +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>T : T +>k : string +>R : R +>Array : T[] +>I : I + + { 1: PathFn, 0: T }[TupleHasIndex]; +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>T : T +>R : R +>StringToNumber : StringToNumber +>I : I +>R : R +>Inc : Inc +>I : I +>T : T +>TupleHasIndex : ({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I] +>R : R +>I : I + +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +>PathTest : "e" +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>a : { b: ["c", { d: "e"; }]; } +>b : ["c", { d: "e"; }] +>d : "e" + +declare function path>(obj: T, path: R): PathFn; +>path : (obj: T, path: R) => { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["1"]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["0"]] +>T : T +>k : string +>R : R +>Array : T[] +>obj : T +>T : T +>path : R +>R : R +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>T : T +>R : R + +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +>obj : { a: { b: ["c", { d: "e"; }]; }; } +>null! as { a: { b: ['c', { d: 'e' }] } } : { a: { b: ["c", { d: "e"; }]; }; } +>null! : never +>null : null +>a : { b: ["c", { d: "e"; }]; } +>b : ["c", { d: "e"; }] +>d : "e" + +const keys = null! as ['a', 'b', '1', 'd']; +>keys : ["a", "b", "1", "d"] +>null! as ['a', 'b', '1', 'd'] : ["a", "b", "1", "d"] +>null! : never +>null : null + +const pathTest = path(obj, keys); +>pathTest : "e" +>path(obj, keys) : "e" +>path : (obj: T, path: R) => { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["1"]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["0"]] +>obj : { a: { b: ["c", { d: "e"; }]; }; } +>keys : ["a", "b", "1", "d"] + +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" + // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; >Fn1 : Fn1 diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index ae0fb791b70a4..6c38ec338f60b 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -46,6 +46,39 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); +// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +type PathFn, I extends string = '0'> = + { 1: PathFn, 0: T }[TupleHasIndex]; +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +declare function path>(obj: T, path: R): PathFn; +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +const keys = null! as ['a', 'b', '1', 'd']; +const pathTest = path(obj, keys); +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; From 4d14c9fb1da5cf6f5db024e8b25c87336d834103 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 10 Sep 2017 02:46:42 +0800 Subject: [PATCH 18/25] add use-case: type substraction / assertion (`!`) --- tests/baselines/reference/typeCall.js | 12 +- tests/baselines/reference/typeCall.symbols | 356 +++++++++++---------- tests/baselines/reference/typeCall.types | 37 ++- tests/cases/compiler/typeCall.ts | 7 +- 4 files changed, 240 insertions(+), 172 deletions(-) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 7ee4930dac778..d7d3d8f624c67 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -107,6 +107,12 @@ let strBool: isBool(string); // 0 let anyBool: isBool(any); // 0 let neverBool: isBool(never); // 0 +type Assert = ((v: U | null | undefined) => U)(T); +let assert: Assert; // string + +type Minus = ((v: U | B) => U)(A); +let noNumbers: Minus; // string + interface ObjectHasStringIndex { // (o: T): T[string]; (o: { [k: string]: any }): '1'; @@ -152,8 +158,8 @@ type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: let a1: () => string; let b1: typeof a1(); -type Assert any> = T(); -let c1: Assert; +type Abc any> = T(); +let c1: Abc; declare function infer1 any>(x: T): T(); infer1(null! as () => number); @@ -221,6 +227,8 @@ var trueBool; // 1 var strBool; // 0 var anyBool; // 0 var neverBool; // 0 +var assert; // string +var noNumbers; // string var ObjectHasStringIndexTestT; // '1' var ObjectHasStringIndexTestF; // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. var a1; diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 242c1b773f2bb..912f14104b739 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -370,272 +370,300 @@ let neverBool: isBool(never); // 0 >neverBool : Symbol(neverBool, Decl(typeCall.ts, 106, 3)) >isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) +type Assert = ((v: U | null | undefined) => U)(T); +>Assert : Symbol(Assert, Decl(typeCall.ts, 106, 29)) +>T : Symbol(T, Decl(typeCall.ts, 108, 12)) +>U : Symbol(U, Decl(typeCall.ts, 108, 19)) +>v : Symbol(v, Decl(typeCall.ts, 108, 22)) +>U : Symbol(U, Decl(typeCall.ts, 108, 19)) +>U : Symbol(U, Decl(typeCall.ts, 108, 19)) +>T : Symbol(T, Decl(typeCall.ts, 108, 12)) + +let assert: Assert; // string +>assert : Symbol(assert, Decl(typeCall.ts, 109, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 106, 29)) + +type Minus = ((v: U | B) => U)(A); +>Minus : Symbol(Minus, Decl(typeCall.ts, 109, 39)) +>A : Symbol(A, Decl(typeCall.ts, 111, 11)) +>B : Symbol(B, Decl(typeCall.ts, 111, 13)) +>U : Symbol(U, Decl(typeCall.ts, 111, 21)) +>v : Symbol(v, Decl(typeCall.ts, 111, 24)) +>U : Symbol(U, Decl(typeCall.ts, 111, 21)) +>B : Symbol(B, Decl(typeCall.ts, 111, 13)) +>U : Symbol(U, Decl(typeCall.ts, 111, 21)) +>A : Symbol(A, Decl(typeCall.ts, 111, 11)) + +let noNumbers: Minus; // string +>noNumbers : Symbol(noNumbers, Decl(typeCall.ts, 112, 3)) +>Minus : Symbol(Minus, Decl(typeCall.ts, 109, 39)) + interface ObjectHasStringIndex { ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 106, 29)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 112, 46)) // (o: T): T[string]; (o: { [k: string]: any }): '1'; ->o : Symbol(o, Decl(typeCall.ts, 110, 3)) ->k : Symbol(k, Decl(typeCall.ts, 110, 9)) +>o : Symbol(o, Decl(typeCall.ts, 116, 3)) +>k : Symbol(k, Decl(typeCall.ts, 116, 9)) (o: {}): '0'; ->o : Symbol(o, Decl(typeCall.ts, 111, 3)) +>o : Symbol(o, Decl(typeCall.ts, 117, 3)) } let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' ->ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 113, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 106, 29)) ->k : Symbol(k, Decl(typeCall.ts, 113, 55)) +>ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 119, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 112, 46)) +>k : Symbol(k, Decl(typeCall.ts, 119, 55)) let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. ->ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 114, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 106, 29)) ->a : Symbol(a, Decl(typeCall.ts, 114, 53)) +>ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 120, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 112, 46)) +>a : Symbol(a, Decl(typeCall.ts, 120, 53)) type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 114, 64)) ->T : Symbol(T, Decl(typeCall.ts, 116, 15)) ->k : Symbol(k, Decl(typeCall.ts, 116, 34)) ->K : Symbol(K, Decl(typeCall.ts, 116, 52)) ->T : Symbol(T, Decl(typeCall.ts, 116, 15)) ->T : Symbol(T, Decl(typeCall.ts, 116, 15)) ->K : Symbol(K, Decl(typeCall.ts, 116, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 120, 64)) +>T : Symbol(T, Decl(typeCall.ts, 122, 15)) +>k : Symbol(k, Decl(typeCall.ts, 122, 34)) +>K : Symbol(K, Decl(typeCall.ts, 122, 52)) +>T : Symbol(T, Decl(typeCall.ts, 122, 15)) +>T : Symbol(T, Decl(typeCall.ts, 122, 15)) +>K : Symbol(K, Decl(typeCall.ts, 122, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 116, 85)) ->T : Symbol(T, Decl(typeCall.ts, 117, 16)) ->k : Symbol(k, Decl(typeCall.ts, 117, 29)) ->K : Symbol(K, Decl(typeCall.ts, 117, 53)) ->T : Symbol(T, Decl(typeCall.ts, 117, 16)) ->T : Symbol(T, Decl(typeCall.ts, 117, 16)) ->K : Symbol(K, Decl(typeCall.ts, 117, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 122, 85)) +>T : Symbol(T, Decl(typeCall.ts, 123, 16)) +>k : Symbol(k, Decl(typeCall.ts, 123, 29)) +>K : Symbol(K, Decl(typeCall.ts, 123, 53)) +>T : Symbol(T, Decl(typeCall.ts, 123, 16)) +>T : Symbol(T, Decl(typeCall.ts, 123, 16)) +>K : Symbol(K, Decl(typeCall.ts, 123, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 117, 82)) ->T : Symbol(T, Decl(typeCall.ts, 118, 22)) ->k : Symbol(k, Decl(typeCall.ts, 118, 35)) ->K : Symbol(K, Decl(typeCall.ts, 118, 65)) ->T : Symbol(T, Decl(typeCall.ts, 118, 22)) ->T : Symbol(T, Decl(typeCall.ts, 118, 22)) ->K : Symbol(K, Decl(typeCall.ts, 118, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 123, 82)) +>T : Symbol(T, Decl(typeCall.ts, 124, 22)) +>k : Symbol(k, Decl(typeCall.ts, 124, 35)) +>K : Symbol(K, Decl(typeCall.ts, 124, 65)) +>T : Symbol(T, Decl(typeCall.ts, 124, 22)) +>T : Symbol(T, Decl(typeCall.ts, 124, 22)) +>K : Symbol(K, Decl(typeCall.ts, 124, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 118, 89)) ->T : Symbol(T, Decl(typeCall.ts, 120, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 120, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 124, 89)) +>T : Symbol(T, Decl(typeCall.ts, 126, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 126, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 121, 5)) ->T : Symbol(T, Decl(typeCall.ts, 120, 12)) +>K : Symbol(K, Decl(typeCall.ts, 127, 5)) +>T : Symbol(T, Decl(typeCall.ts, 126, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 122, 5)) +>key : Symbol(key, Decl(typeCall.ts, 128, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 120, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 126, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 123, 7)) ->T : Symbol(T, Decl(typeCall.ts, 125, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 118, 89)) ->T : Symbol(T, Decl(typeCall.ts, 125, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 129, 7)) +>T : Symbol(T, Decl(typeCall.ts, 131, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 124, 89)) +>T : Symbol(T, Decl(typeCall.ts, 131, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 125, 59)) ->T : Symbol(T, Decl(typeCall.ts, 126, 15)) ->k : Symbol(k, Decl(typeCall.ts, 126, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 126, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 131, 59)) +>T : Symbol(T, Decl(typeCall.ts, 132, 15)) +>k : Symbol(k, Decl(typeCall.ts, 132, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 132, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 127, 5)) ->T : Symbol(T, Decl(typeCall.ts, 126, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 118, 89)) ->T : Symbol(T, Decl(typeCall.ts, 126, 15)) ->K : Symbol(K, Decl(typeCall.ts, 127, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 126, 52)) +>K : Symbol(K, Decl(typeCall.ts, 133, 5)) +>T : Symbol(T, Decl(typeCall.ts, 132, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 124, 89)) +>T : Symbol(T, Decl(typeCall.ts, 132, 15)) +>K : Symbol(K, Decl(typeCall.ts, 133, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 132, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 128, 2)) ->T : Symbol(T, Decl(typeCall.ts, 130, 15)) ->T : Symbol(T, Decl(typeCall.ts, 130, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 134, 2)) +>T : Symbol(T, Decl(typeCall.ts, 136, 15)) +>T : Symbol(T, Decl(typeCall.ts, 136, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 130, 50)) ->T : Symbol(T, Decl(typeCall.ts, 132, 12)) ->K : Symbol(K, Decl(typeCall.ts, 132, 38)) ->T : Symbol(T, Decl(typeCall.ts, 132, 12)) ->T : Symbol(T, Decl(typeCall.ts, 132, 12)) ->K : Symbol(K, Decl(typeCall.ts, 132, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 136, 50)) +>T : Symbol(T, Decl(typeCall.ts, 138, 12)) +>K : Symbol(K, Decl(typeCall.ts, 138, 38)) +>T : Symbol(T, Decl(typeCall.ts, 138, 12)) +>T : Symbol(T, Decl(typeCall.ts, 138, 12)) +>K : Symbol(K, Decl(typeCall.ts, 138, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 132, 66)) ->T : Symbol(T, Decl(typeCall.ts, 133, 12)) ->k : Symbol(k, Decl(typeCall.ts, 133, 31)) ->K : Symbol(K, Decl(typeCall.ts, 133, 61)) ->T : Symbol(T, Decl(typeCall.ts, 133, 12)) ->T : Symbol(T, Decl(typeCall.ts, 133, 12)) ->K : Symbol(K, Decl(typeCall.ts, 133, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 138, 66)) +>T : Symbol(T, Decl(typeCall.ts, 139, 12)) +>k : Symbol(k, Decl(typeCall.ts, 139, 31)) +>K : Symbol(K, Decl(typeCall.ts, 139, 61)) +>T : Symbol(T, Decl(typeCall.ts, 139, 12)) +>T : Symbol(T, Decl(typeCall.ts, 139, 12)) +>K : Symbol(K, Decl(typeCall.ts, 139, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 135, 12)) +>x : Symbol(x, Decl(typeCall.ts, 141, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 136, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 137, 14)) ->value : Symbol(value, Decl(typeCall.ts, 137, 28)) +>z : Symbol(z, Decl(typeCall.ts, 142, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 143, 14)) +>value : Symbol(value, Decl(typeCall.ts, 143, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 138, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 144, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 140, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 116, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 146, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 122, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 141, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 114, 64)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 147, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 120, 64)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 142, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 117, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 148, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 123, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 143, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 149, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 144, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 128, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 150, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 134, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 145, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 151, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 146, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 125, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 152, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 131, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 147, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 130, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 153, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 136, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 148, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 132, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 133, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 154, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 138, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 151, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 157, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 152, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 151, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 158, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 157, 3)) -type Assert any> = T(); ->Assert : Symbol(Assert, Decl(typeCall.ts, 152, 20)) ->T : Symbol(T, Decl(typeCall.ts, 153, 12)) ->T : Symbol(T, Decl(typeCall.ts, 153, 12)) +type Abc any> = T(); +>Abc : Symbol(Abc, Decl(typeCall.ts, 158, 20)) +>T : Symbol(T, Decl(typeCall.ts, 159, 9)) +>T : Symbol(T, Decl(typeCall.ts, 159, 9)) -let c1: Assert; ->c1 : Symbol(c1, Decl(typeCall.ts, 154, 3)) ->Assert : Symbol(Assert, Decl(typeCall.ts, 152, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 151, 3)) +let c1: Abc; +>c1 : Symbol(c1, Decl(typeCall.ts, 160, 3)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 158, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 157, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 154, 26)) ->T : Symbol(T, Decl(typeCall.ts, 156, 24)) ->x : Symbol(x, Decl(typeCall.ts, 156, 45)) ->T : Symbol(T, Decl(typeCall.ts, 156, 24)) ->T : Symbol(T, Decl(typeCall.ts, 156, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 160, 23)) +>T : Symbol(T, Decl(typeCall.ts, 162, 24)) +>x : Symbol(x, Decl(typeCall.ts, 162, 45)) +>T : Symbol(T, Decl(typeCall.ts, 162, 24)) +>T : Symbol(T, Decl(typeCall.ts, 162, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 154, 26)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 160, 23)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 157, 30)) ->T : Symbol(T, Decl(typeCall.ts, 159, 24)) ->x : Symbol(x, Decl(typeCall.ts, 159, 45)) ->a : Symbol(a, Decl(typeCall.ts, 159, 49)) ->T : Symbol(T, Decl(typeCall.ts, 159, 24)) ->T : Symbol(T, Decl(typeCall.ts, 159, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 163, 30)) +>T : Symbol(T, Decl(typeCall.ts, 165, 24)) +>x : Symbol(x, Decl(typeCall.ts, 165, 45)) +>a : Symbol(a, Decl(typeCall.ts, 165, 49)) +>T : Symbol(T, Decl(typeCall.ts, 165, 24)) +>T : Symbol(T, Decl(typeCall.ts, 165, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 157, 30)) ->a : Symbol(a, Decl(typeCall.ts, 160, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 163, 30)) +>a : Symbol(a, Decl(typeCall.ts, 166, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 160, 37)) ->T : Symbol(T, Decl(typeCall.ts, 162, 24)) ->x : Symbol(x, Decl(typeCall.ts, 162, 27)) ->a : Symbol(a, Decl(typeCall.ts, 162, 31)) ->T : Symbol(T, Decl(typeCall.ts, 162, 24)) ->T : Symbol(T, Decl(typeCall.ts, 162, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 166, 37)) +>T : Symbol(T, Decl(typeCall.ts, 168, 24)) +>x : Symbol(x, Decl(typeCall.ts, 168, 27)) +>a : Symbol(a, Decl(typeCall.ts, 168, 31)) +>T : Symbol(T, Decl(typeCall.ts, 168, 24)) +>T : Symbol(T, Decl(typeCall.ts, 168, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 160, 37)) ->a : Symbol(a, Decl(typeCall.ts, 163, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 166, 37)) +>a : Symbol(a, Decl(typeCall.ts, 169, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 164, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 160, 37)) ->a : Symbol(a, Decl(typeCall.ts, 164, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 170, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 166, 37)) +>a : Symbol(a, Decl(typeCall.ts, 170, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 164, 58)) ->T : Symbol(T, Decl(typeCall.ts, 166, 24)) ->x : Symbol(x, Decl(typeCall.ts, 166, 27)) ->T : Symbol(T, Decl(typeCall.ts, 166, 24)) ->y : Symbol(y, Decl(typeCall.ts, 166, 32)) ->T : Symbol(T, Decl(typeCall.ts, 166, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 170, 58)) +>T : Symbol(T, Decl(typeCall.ts, 172, 24)) +>x : Symbol(x, Decl(typeCall.ts, 172, 27)) +>T : Symbol(T, Decl(typeCall.ts, 172, 24)) +>y : Symbol(y, Decl(typeCall.ts, 172, 32)) +>T : Symbol(T, Decl(typeCall.ts, 172, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 164, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 170, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 167, 19)) ->T : Symbol(T, Decl(typeCall.ts, 169, 23)) ->x : Symbol(x, Decl(typeCall.ts, 169, 26)) ->T : Symbol(T, Decl(typeCall.ts, 169, 23)) ->y : Symbol(y, Decl(typeCall.ts, 169, 31)) ->T : Symbol(T, Decl(typeCall.ts, 169, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 173, 19)) +>T : Symbol(T, Decl(typeCall.ts, 175, 23)) +>x : Symbol(x, Decl(typeCall.ts, 175, 26)) +>T : Symbol(T, Decl(typeCall.ts, 175, 23)) +>y : Symbol(y, Decl(typeCall.ts, 175, 31)) +>T : Symbol(T, Decl(typeCall.ts, 175, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 170, 9)) ->T : Symbol(T, Decl(typeCall.ts, 169, 23)) ->x : Symbol(x, Decl(typeCall.ts, 169, 26)) +>a : Symbol(a, Decl(typeCall.ts, 176, 9)) +>T : Symbol(T, Decl(typeCall.ts, 175, 23)) +>x : Symbol(x, Decl(typeCall.ts, 175, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 171, 9)) ->T : Symbol(T, Decl(typeCall.ts, 169, 23)) ->y : Symbol(y, Decl(typeCall.ts, 169, 31)) +>b : Symbol(b, Decl(typeCall.ts, 177, 9)) +>T : Symbol(T, Decl(typeCall.ts, 175, 23)) +>y : Symbol(y, Decl(typeCall.ts, 175, 31)) } function comparability(x: T, y: () => T) { ->comparability : Symbol(comparability, Decl(typeCall.ts, 172, 1)) ->T : Symbol(T, Decl(typeCall.ts, 174, 23)) ->x : Symbol(x, Decl(typeCall.ts, 174, 26)) ->T : Symbol(T, Decl(typeCall.ts, 174, 23)) ->y : Symbol(y, Decl(typeCall.ts, 174, 31)) ->T : Symbol(T, Decl(typeCall.ts, 174, 23)) +>comparability : Symbol(comparability, Decl(typeCall.ts, 178, 1)) +>T : Symbol(T, Decl(typeCall.ts, 180, 23)) +>x : Symbol(x, Decl(typeCall.ts, 180, 26)) +>T : Symbol(T, Decl(typeCall.ts, 180, 23)) +>y : Symbol(y, Decl(typeCall.ts, 180, 31)) +>T : Symbol(T, Decl(typeCall.ts, 180, 23)) x === x; ->x : Symbol(x, Decl(typeCall.ts, 174, 26)) ->x : Symbol(x, Decl(typeCall.ts, 174, 26)) +>x : Symbol(x, Decl(typeCall.ts, 180, 26)) +>x : Symbol(x, Decl(typeCall.ts, 180, 26)) y === y; ->y : Symbol(y, Decl(typeCall.ts, 174, 31)) ->y : Symbol(y, Decl(typeCall.ts, 174, 31)) +>y : Symbol(y, Decl(typeCall.ts, 180, 31)) +>y : Symbol(y, Decl(typeCall.ts, 180, 31)) // x === y; // rightfully errors } diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 7957d07812de3..6faa4c24d44af 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -391,6 +391,35 @@ let neverBool: isBool(never); // 0 >neverBool : "0" >isBool : isT +type Assert = ((v: U | null | undefined) => U)(T); +>Assert : ((v: U | null | undefined) => U)(T) +>T : T +>U : U +>v : U | null | undefined +>U : U +>null : null +>U : U +>T : T + +let assert: Assert; // string +>assert : string +>Assert : ((v: U | null | undefined) => U)(T) + +type Minus = ((v: U | B) => U)(A); +>Minus : ((v: B | U) => U)(A) +>A : A +>B : B +>U : U +>v : B | U +>U : U +>B : B +>U : U +>A : A + +let noNumbers: Minus; // string +>noNumbers : string +>Minus : ((v: B | U) => U)(A) + interface ObjectHasStringIndex { >ObjectHasStringIndex : ObjectHasStringIndex @@ -563,14 +592,14 @@ let b1: typeof a1(); >b1 : string >a1 : () => string -type Assert any> = T(); ->Assert : T() +type Abc any> = T(); +>Abc : T() >T : T >T : T -let c1: Assert; +let c1: Abc; >c1 : string ->Assert : T() +>Abc : T() >a1 : () => string declare function infer1 any>(x: T): T(); diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 6c38ec338f60b..e329ca8cf456d 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -110,6 +110,9 @@ let strBool: isBool(string); // 0 let anyBool: isBool(any); // 0 let neverBool: isBool(never); // 0 +type Assert = ((v: U | null | undefined) => U)(T); +let x: Assert; // string + interface ObjectHasStringIndex { // (o: T): T[string]; (o: { [k: string]: any }): '1'; @@ -155,8 +158,8 @@ type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: let a1: () => string; let b1: typeof a1(); -type Assert any> = T(); -let c1: Assert; +type Abc any> = T(); +let c1: Abc; declare function infer1 any>(x: T): T(); infer1(null! as () => number); From a8fc55a3bbc2718cd9cf2edfa2b736dd55c9d1fa Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 10 Sep 2017 02:47:55 +0800 Subject: [PATCH 19/25] use-case: `promised` (WIP, breaks on unions) --- tests/baselines/reference/typeCall.js | 39 ++ tests/baselines/reference/typeCall.symbols | 458 +++++++++++++-------- tests/baselines/reference/typeCall.types | 140 +++++++ tests/cases/compiler/typeCall.ts | 35 +- 4 files changed, 507 insertions(+), 165 deletions(-) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index d7d3d8f624c67..d2c321b43afe6 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -113,6 +113,36 @@ let assert: Assert; // string type Minus = ((v: U | B) => U)(A); let noNumbers: Minus; // string +interface UnwrapPromise { + (v: PromiseLike): UnwrapPromise(U); + (v: U): U; +}; +declare const testUnwrap1: UnwrapPromise(string); +declare const testUnwrap2: UnwrapPromise(Promise); +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +declare function myThen( + prom: Promise, + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +declare const pr: Promise; +declare function f(x: number): Promise; +declare function g(x: number): number | Promise; +const testThen = myThen(pr, f, g); + +interface Promise { + then( + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +} +// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter +// of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { + if (x < 0) return f(x); + return x; +}); + interface ObjectHasStringIndex { // (o: T): T[string]; (o: { [k: string]: any }): '1'; @@ -229,6 +259,15 @@ var anyBool; // 0 var neverBool; // 0 var assert; // string var noNumbers; // string +; +var testThen = myThen(pr, f, g); +// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter +// of type '(value: number) => string | PromiseLike'; +var tryProm = pr.then(function (x) { + if (x < 0) + return f(x); + return x; +}); var ObjectHasStringIndexTestT; // '1' var ObjectHasStringIndexTestF; // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. var a1; diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 912f14104b739..6d28a8da46b00 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -44,12 +44,12 @@ let a = 'foo'; >a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) type f = typeof f4(typeof a); ->f : Symbol(f, Decl(typeCall.ts, 16, 14)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) >f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) >a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) type g = (() => 1)(); ->g : Symbol(g, Decl(typeCall.ts, 17, 29)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 127, 47)) type Id = (v: T) => T; >Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) @@ -398,272 +398,402 @@ let noNumbers: Minus; // string >noNumbers : Symbol(noNumbers, Decl(typeCall.ts, 112, 3)) >Minus : Symbol(Minus, Decl(typeCall.ts, 109, 39)) +interface UnwrapPromise { +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) + + (v: PromiseLike): UnwrapPromise(U); +>U : Symbol(U, Decl(typeCall.ts, 115, 3)) +>v : Symbol(v, Decl(typeCall.ts, 115, 6)) +>PromiseLike : Symbol(PromiseLike, Decl(lib.d.ts, --, --)) +>U : Symbol(U, Decl(typeCall.ts, 115, 3)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>U : Symbol(U, Decl(typeCall.ts, 115, 3)) + + (v: U): U; +>U : Symbol(U, Decl(typeCall.ts, 116, 3)) +>v : Symbol(v, Decl(typeCall.ts, 116, 6)) +>U : Symbol(U, Decl(typeCall.ts, 116, 3)) +>U : Symbol(U, Decl(typeCall.ts, 116, 3)) + +}; +declare const testUnwrap1: UnwrapPromise(string); +>testUnwrap1 : Symbol(testUnwrap1, Decl(typeCall.ts, 118, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) + +declare const testUnwrap2: UnwrapPromise(Promise); +>testUnwrap2 : Symbol(testUnwrap2, Decl(typeCall.ts, 119, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) + +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +>testUnwrap3 : Symbol(testUnwrap3, Decl(typeCall.ts, 120, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) + +declare function myThen( +>myThen : Symbol(myThen, Decl(typeCall.ts, 120, 68)) +>T : Symbol(T, Decl(typeCall.ts, 121, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 121, 26)) +>T : Symbol(T, Decl(typeCall.ts, 121, 24)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 121, 40)) + + prom: Promise, +>prom : Symbol(prom, Decl(typeCall.ts, 121, 59)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>T : Symbol(T, Decl(typeCall.ts, 121, 24)) + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 122, 25)) +>value : Symbol(value, Decl(typeCall.ts, 123, 24)) +>T : Symbol(T, Decl(typeCall.ts, 121, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 121, 26)) + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 123, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 124, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 121, 40)) + + ): Promise; +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 121, 26)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 121, 40)) + +declare const pr: Promise; +>pr : Symbol(pr, Decl(typeCall.ts, 126, 13)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) + +declare function f(x: number): Promise; +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) +>x : Symbol(x, Decl(typeCall.ts, 127, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) + +declare function g(x: number): number | Promise; +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 127, 47)) +>x : Symbol(x, Decl(typeCall.ts, 128, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) + +const testThen = myThen(pr, f, g); +>testThen : Symbol(testThen, Decl(typeCall.ts, 129, 5)) +>myThen : Symbol(myThen, Decl(typeCall.ts, 120, 68)) +>pr : Symbol(pr, Decl(typeCall.ts, 126, 13)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 127, 47)) + +interface Promise { +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 18)) + + then( +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 22)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 132, 9)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 18)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 132, 22)) + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 132, 41)) +>value : Symbol(value, Decl(typeCall.ts, 133, 24)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 18)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 132, 9)) + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 133, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 134, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 132, 22)) + + ): Promise; +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 132, 9)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 132, 22)) +} +// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter +// of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { +>tryProm : Symbol(tryProm, Decl(typeCall.ts, 139, 5)) +>pr.then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 22)) +>pr : Symbol(pr, Decl(typeCall.ts, 126, 13)) +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 22)) +>x : Symbol(x, Decl(typeCall.ts, 139, 25)) + + if (x < 0) return f(x); +>x : Symbol(x, Decl(typeCall.ts, 139, 25)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) +>x : Symbol(x, Decl(typeCall.ts, 139, 25)) + + return x; +>x : Symbol(x, Decl(typeCall.ts, 139, 25)) + +}); + interface ObjectHasStringIndex { ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 112, 46)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 142, 3)) // (o: T): T[string]; (o: { [k: string]: any }): '1'; ->o : Symbol(o, Decl(typeCall.ts, 116, 3)) ->k : Symbol(k, Decl(typeCall.ts, 116, 9)) +>o : Symbol(o, Decl(typeCall.ts, 146, 3)) +>k : Symbol(k, Decl(typeCall.ts, 146, 9)) (o: {}): '0'; ->o : Symbol(o, Decl(typeCall.ts, 117, 3)) +>o : Symbol(o, Decl(typeCall.ts, 147, 3)) } let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' ->ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 119, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 112, 46)) ->k : Symbol(k, Decl(typeCall.ts, 119, 55)) +>ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 149, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 142, 3)) +>k : Symbol(k, Decl(typeCall.ts, 149, 55)) let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. ->ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 120, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 112, 46)) ->a : Symbol(a, Decl(typeCall.ts, 120, 53)) +>ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 150, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 142, 3)) +>a : Symbol(a, Decl(typeCall.ts, 150, 53)) type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 120, 64)) ->T : Symbol(T, Decl(typeCall.ts, 122, 15)) ->k : Symbol(k, Decl(typeCall.ts, 122, 34)) ->K : Symbol(K, Decl(typeCall.ts, 122, 52)) ->T : Symbol(T, Decl(typeCall.ts, 122, 15)) ->T : Symbol(T, Decl(typeCall.ts, 122, 15)) ->K : Symbol(K, Decl(typeCall.ts, 122, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 150, 64)) +>T : Symbol(T, Decl(typeCall.ts, 152, 15)) +>k : Symbol(k, Decl(typeCall.ts, 152, 34)) +>K : Symbol(K, Decl(typeCall.ts, 152, 52)) +>T : Symbol(T, Decl(typeCall.ts, 152, 15)) +>T : Symbol(T, Decl(typeCall.ts, 152, 15)) +>K : Symbol(K, Decl(typeCall.ts, 152, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 122, 85)) ->T : Symbol(T, Decl(typeCall.ts, 123, 16)) ->k : Symbol(k, Decl(typeCall.ts, 123, 29)) ->K : Symbol(K, Decl(typeCall.ts, 123, 53)) ->T : Symbol(T, Decl(typeCall.ts, 123, 16)) ->T : Symbol(T, Decl(typeCall.ts, 123, 16)) ->K : Symbol(K, Decl(typeCall.ts, 123, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 152, 85)) +>T : Symbol(T, Decl(typeCall.ts, 153, 16)) +>k : Symbol(k, Decl(typeCall.ts, 153, 29)) +>K : Symbol(K, Decl(typeCall.ts, 153, 53)) +>T : Symbol(T, Decl(typeCall.ts, 153, 16)) +>T : Symbol(T, Decl(typeCall.ts, 153, 16)) +>K : Symbol(K, Decl(typeCall.ts, 153, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 123, 82)) ->T : Symbol(T, Decl(typeCall.ts, 124, 22)) ->k : Symbol(k, Decl(typeCall.ts, 124, 35)) ->K : Symbol(K, Decl(typeCall.ts, 124, 65)) ->T : Symbol(T, Decl(typeCall.ts, 124, 22)) ->T : Symbol(T, Decl(typeCall.ts, 124, 22)) ->K : Symbol(K, Decl(typeCall.ts, 124, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 153, 82)) +>T : Symbol(T, Decl(typeCall.ts, 154, 22)) +>k : Symbol(k, Decl(typeCall.ts, 154, 35)) +>K : Symbol(K, Decl(typeCall.ts, 154, 65)) +>T : Symbol(T, Decl(typeCall.ts, 154, 22)) +>T : Symbol(T, Decl(typeCall.ts, 154, 22)) +>K : Symbol(K, Decl(typeCall.ts, 154, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 124, 89)) ->T : Symbol(T, Decl(typeCall.ts, 126, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 126, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 154, 89)) +>T : Symbol(T, Decl(typeCall.ts, 156, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 156, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 127, 5)) ->T : Symbol(T, Decl(typeCall.ts, 126, 12)) +>K : Symbol(K, Decl(typeCall.ts, 157, 5)) +>T : Symbol(T, Decl(typeCall.ts, 156, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 128, 5)) +>key : Symbol(key, Decl(typeCall.ts, 158, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 126, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 156, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 129, 7)) ->T : Symbol(T, Decl(typeCall.ts, 131, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 124, 89)) ->T : Symbol(T, Decl(typeCall.ts, 131, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 159, 7)) +>T : Symbol(T, Decl(typeCall.ts, 161, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 154, 89)) +>T : Symbol(T, Decl(typeCall.ts, 161, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 131, 59)) ->T : Symbol(T, Decl(typeCall.ts, 132, 15)) ->k : Symbol(k, Decl(typeCall.ts, 132, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 132, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 161, 59)) +>T : Symbol(T, Decl(typeCall.ts, 162, 15)) +>k : Symbol(k, Decl(typeCall.ts, 162, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 162, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 133, 5)) ->T : Symbol(T, Decl(typeCall.ts, 132, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 124, 89)) ->T : Symbol(T, Decl(typeCall.ts, 132, 15)) ->K : Symbol(K, Decl(typeCall.ts, 133, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 132, 52)) +>K : Symbol(K, Decl(typeCall.ts, 163, 5)) +>T : Symbol(T, Decl(typeCall.ts, 162, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 154, 89)) +>T : Symbol(T, Decl(typeCall.ts, 162, 15)) +>K : Symbol(K, Decl(typeCall.ts, 163, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 162, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 134, 2)) ->T : Symbol(T, Decl(typeCall.ts, 136, 15)) ->T : Symbol(T, Decl(typeCall.ts, 136, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 164, 2)) +>T : Symbol(T, Decl(typeCall.ts, 166, 15)) +>T : Symbol(T, Decl(typeCall.ts, 166, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 136, 50)) ->T : Symbol(T, Decl(typeCall.ts, 138, 12)) ->K : Symbol(K, Decl(typeCall.ts, 138, 38)) ->T : Symbol(T, Decl(typeCall.ts, 138, 12)) ->T : Symbol(T, Decl(typeCall.ts, 138, 12)) ->K : Symbol(K, Decl(typeCall.ts, 138, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 166, 50)) +>T : Symbol(T, Decl(typeCall.ts, 168, 12)) +>K : Symbol(K, Decl(typeCall.ts, 168, 38)) +>T : Symbol(T, Decl(typeCall.ts, 168, 12)) +>T : Symbol(T, Decl(typeCall.ts, 168, 12)) +>K : Symbol(K, Decl(typeCall.ts, 168, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 138, 66)) ->T : Symbol(T, Decl(typeCall.ts, 139, 12)) ->k : Symbol(k, Decl(typeCall.ts, 139, 31)) ->K : Symbol(K, Decl(typeCall.ts, 139, 61)) ->T : Symbol(T, Decl(typeCall.ts, 139, 12)) ->T : Symbol(T, Decl(typeCall.ts, 139, 12)) ->K : Symbol(K, Decl(typeCall.ts, 139, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 168, 66)) +>T : Symbol(T, Decl(typeCall.ts, 169, 12)) +>k : Symbol(k, Decl(typeCall.ts, 169, 31)) +>K : Symbol(K, Decl(typeCall.ts, 169, 61)) +>T : Symbol(T, Decl(typeCall.ts, 169, 12)) +>T : Symbol(T, Decl(typeCall.ts, 169, 12)) +>K : Symbol(K, Decl(typeCall.ts, 169, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 141, 12)) +>x : Symbol(x, Decl(typeCall.ts, 171, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 142, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 143, 14)) ->value : Symbol(value, Decl(typeCall.ts, 143, 28)) +>z : Symbol(z, Decl(typeCall.ts, 172, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 173, 14)) +>value : Symbol(value, Decl(typeCall.ts, 173, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 144, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 174, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 146, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 122, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 176, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 152, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 147, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 120, 64)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 177, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 150, 64)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 148, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 123, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 178, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 153, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 149, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 179, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 150, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 134, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 180, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 164, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 151, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 181, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 152, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 131, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 182, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 161, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 153, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 136, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 183, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 166, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 154, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 138, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 139, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 184, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 168, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 157, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 187, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 158, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 157, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 188, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 187, 3)) type Abc any> = T(); ->Abc : Symbol(Abc, Decl(typeCall.ts, 158, 20)) ->T : Symbol(T, Decl(typeCall.ts, 159, 9)) ->T : Symbol(T, Decl(typeCall.ts, 159, 9)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 188, 20)) +>T : Symbol(T, Decl(typeCall.ts, 189, 9)) +>T : Symbol(T, Decl(typeCall.ts, 189, 9)) let c1: Abc; ->c1 : Symbol(c1, Decl(typeCall.ts, 160, 3)) ->Abc : Symbol(Abc, Decl(typeCall.ts, 158, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 157, 3)) +>c1 : Symbol(c1, Decl(typeCall.ts, 190, 3)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 188, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 187, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 160, 23)) ->T : Symbol(T, Decl(typeCall.ts, 162, 24)) ->x : Symbol(x, Decl(typeCall.ts, 162, 45)) ->T : Symbol(T, Decl(typeCall.ts, 162, 24)) ->T : Symbol(T, Decl(typeCall.ts, 162, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 190, 23)) +>T : Symbol(T, Decl(typeCall.ts, 192, 24)) +>x : Symbol(x, Decl(typeCall.ts, 192, 45)) +>T : Symbol(T, Decl(typeCall.ts, 192, 24)) +>T : Symbol(T, Decl(typeCall.ts, 192, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 160, 23)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 190, 23)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 163, 30)) ->T : Symbol(T, Decl(typeCall.ts, 165, 24)) ->x : Symbol(x, Decl(typeCall.ts, 165, 45)) ->a : Symbol(a, Decl(typeCall.ts, 165, 49)) ->T : Symbol(T, Decl(typeCall.ts, 165, 24)) ->T : Symbol(T, Decl(typeCall.ts, 165, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 193, 30)) +>T : Symbol(T, Decl(typeCall.ts, 195, 24)) +>x : Symbol(x, Decl(typeCall.ts, 195, 45)) +>a : Symbol(a, Decl(typeCall.ts, 195, 49)) +>T : Symbol(T, Decl(typeCall.ts, 195, 24)) +>T : Symbol(T, Decl(typeCall.ts, 195, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 163, 30)) ->a : Symbol(a, Decl(typeCall.ts, 166, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 193, 30)) +>a : Symbol(a, Decl(typeCall.ts, 196, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 166, 37)) ->T : Symbol(T, Decl(typeCall.ts, 168, 24)) ->x : Symbol(x, Decl(typeCall.ts, 168, 27)) ->a : Symbol(a, Decl(typeCall.ts, 168, 31)) ->T : Symbol(T, Decl(typeCall.ts, 168, 24)) ->T : Symbol(T, Decl(typeCall.ts, 168, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 196, 37)) +>T : Symbol(T, Decl(typeCall.ts, 198, 24)) +>x : Symbol(x, Decl(typeCall.ts, 198, 27)) +>a : Symbol(a, Decl(typeCall.ts, 198, 31)) +>T : Symbol(T, Decl(typeCall.ts, 198, 24)) +>T : Symbol(T, Decl(typeCall.ts, 198, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 166, 37)) ->a : Symbol(a, Decl(typeCall.ts, 169, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 196, 37)) +>a : Symbol(a, Decl(typeCall.ts, 199, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 170, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 166, 37)) ->a : Symbol(a, Decl(typeCall.ts, 170, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 200, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 196, 37)) +>a : Symbol(a, Decl(typeCall.ts, 200, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 170, 58)) ->T : Symbol(T, Decl(typeCall.ts, 172, 24)) ->x : Symbol(x, Decl(typeCall.ts, 172, 27)) ->T : Symbol(T, Decl(typeCall.ts, 172, 24)) ->y : Symbol(y, Decl(typeCall.ts, 172, 32)) ->T : Symbol(T, Decl(typeCall.ts, 172, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 200, 58)) +>T : Symbol(T, Decl(typeCall.ts, 202, 24)) +>x : Symbol(x, Decl(typeCall.ts, 202, 27)) +>T : Symbol(T, Decl(typeCall.ts, 202, 24)) +>y : Symbol(y, Decl(typeCall.ts, 202, 32)) +>T : Symbol(T, Decl(typeCall.ts, 202, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 170, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 200, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 173, 19)) ->T : Symbol(T, Decl(typeCall.ts, 175, 23)) ->x : Symbol(x, Decl(typeCall.ts, 175, 26)) ->T : Symbol(T, Decl(typeCall.ts, 175, 23)) ->y : Symbol(y, Decl(typeCall.ts, 175, 31)) ->T : Symbol(T, Decl(typeCall.ts, 175, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 203, 19)) +>T : Symbol(T, Decl(typeCall.ts, 205, 23)) +>x : Symbol(x, Decl(typeCall.ts, 205, 26)) +>T : Symbol(T, Decl(typeCall.ts, 205, 23)) +>y : Symbol(y, Decl(typeCall.ts, 205, 31)) +>T : Symbol(T, Decl(typeCall.ts, 205, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 176, 9)) ->T : Symbol(T, Decl(typeCall.ts, 175, 23)) ->x : Symbol(x, Decl(typeCall.ts, 175, 26)) +>a : Symbol(a, Decl(typeCall.ts, 206, 9)) +>T : Symbol(T, Decl(typeCall.ts, 205, 23)) +>x : Symbol(x, Decl(typeCall.ts, 205, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 177, 9)) ->T : Symbol(T, Decl(typeCall.ts, 175, 23)) ->y : Symbol(y, Decl(typeCall.ts, 175, 31)) +>b : Symbol(b, Decl(typeCall.ts, 207, 9)) +>T : Symbol(T, Decl(typeCall.ts, 205, 23)) +>y : Symbol(y, Decl(typeCall.ts, 205, 31)) } function comparability(x: T, y: () => T) { ->comparability : Symbol(comparability, Decl(typeCall.ts, 178, 1)) ->T : Symbol(T, Decl(typeCall.ts, 180, 23)) ->x : Symbol(x, Decl(typeCall.ts, 180, 26)) ->T : Symbol(T, Decl(typeCall.ts, 180, 23)) ->y : Symbol(y, Decl(typeCall.ts, 180, 31)) ->T : Symbol(T, Decl(typeCall.ts, 180, 23)) +>comparability : Symbol(comparability, Decl(typeCall.ts, 208, 1)) +>T : Symbol(T, Decl(typeCall.ts, 210, 23)) +>x : Symbol(x, Decl(typeCall.ts, 210, 26)) +>T : Symbol(T, Decl(typeCall.ts, 210, 23)) +>y : Symbol(y, Decl(typeCall.ts, 210, 31)) +>T : Symbol(T, Decl(typeCall.ts, 210, 23)) x === x; ->x : Symbol(x, Decl(typeCall.ts, 180, 26)) ->x : Symbol(x, Decl(typeCall.ts, 180, 26)) +>x : Symbol(x, Decl(typeCall.ts, 210, 26)) +>x : Symbol(x, Decl(typeCall.ts, 210, 26)) y === y; ->y : Symbol(y, Decl(typeCall.ts, 180, 31)) ->y : Symbol(y, Decl(typeCall.ts, 180, 31)) +>y : Symbol(y, Decl(typeCall.ts, 210, 31)) +>y : Symbol(y, Decl(typeCall.ts, 210, 31)) // x === y; // rightfully errors } diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 6faa4c24d44af..ae3f434d3018d 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -420,6 +420,146 @@ let noNumbers: Minus; // string >noNumbers : string >Minus : ((v: B | U) => U)(A) +interface UnwrapPromise { +>UnwrapPromise : UnwrapPromise + + (v: PromiseLike): UnwrapPromise(U); +>U : U +>v : PromiseLike +>PromiseLike : PromiseLike +>U : U +>UnwrapPromise : UnwrapPromise +>U : U + + (v: U): U; +>U : U +>v : U +>U : U +>U : U + +}; +declare const testUnwrap1: UnwrapPromise(string); +>testUnwrap1 : string +>UnwrapPromise : UnwrapPromise + +declare const testUnwrap2: UnwrapPromise(Promise); +>testUnwrap2 : string +>UnwrapPromise : UnwrapPromise +>Promise : Promise + +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +>testUnwrap3 : boolean | Promise +>UnwrapPromise : UnwrapPromise +>Promise : Promise + +declare function myThen( +>myThen : (prom: Promise, onfulfilled?: ((value: T) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined) => Promise +>T : T +>TResult1 : TResult1 +>T : T +>TResult2 : TResult2 + + prom: Promise, +>prom : Promise +>Promise : Promise +>T : T + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : ((value: T) => TResult1) | null | undefined +>value : T +>T : T +>TResult1 : TResult1 +>null : null + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : ((reason: any) => TResult2) | null | undefined +>reason : any +>TResult2 : TResult2 +>null : null + + ): Promise; +>Promise : Promise +>UnwrapPromise : UnwrapPromise +>TResult1 : TResult1 +>UnwrapPromise : UnwrapPromise +>TResult2 : TResult2 + +declare const pr: Promise; +>pr : Promise +>Promise : Promise + +declare function f(x: number): Promise; +>f : (x: number) => Promise +>x : number +>Promise : Promise + +declare function g(x: number): number | Promise; +>g : (x: number) => number | Promise +>x : number +>Promise : Promise + +const testThen = myThen(pr, f, g); +>testThen : Promise> +>myThen(pr, f, g) : Promise> +>myThen : (prom: Promise, onfulfilled?: ((value: T) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined) => Promise +>pr : Promise +>f : (x: number) => Promise +>g : (x: number) => number | Promise + +interface Promise { +>Promise : Promise +>T : T + + then( +>then : { (onfulfilled?: ((value: T) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: T) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } +>TResult1 : TResult1 +>T : T +>TResult2 : TResult2 + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : ((value: T) => TResult1) | null | undefined +>value : T +>T : T +>TResult1 : TResult1 +>null : null + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : ((reason: any) => TResult2) | null | undefined +>reason : any +>TResult2 : TResult2 +>null : null + + ): Promise; +>Promise : Promise +>UnwrapPromise : UnwrapPromise +>TResult1 : TResult1 +>UnwrapPromise : UnwrapPromise +>TResult2 : TResult2 +} +// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter +// of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { +>tryProm : Promise> +>pr.then((x: number) => { if (x < 0) return f(x); return x;}) : Promise> +>pr.then : { (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } +>pr : Promise +>then : { (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } +>(x: number) => { if (x < 0) return f(x); return x;} : (x: number) => number | Promise +>x : number + + if (x < 0) return f(x); +>x < 0 : boolean +>x : number +>0 : 0 +>f(x) : Promise +>f : (x: number) => Promise +>x : number + + return x; +>x : number + +}); + interface ObjectHasStringIndex { >ObjectHasStringIndex : ObjectHasStringIndex diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index e329ca8cf456d..2d18c5864e25a 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -111,7 +111,40 @@ let anyBool: isBool(any); // 0 let neverBool: isBool(never); // 0 type Assert = ((v: U | null | undefined) => U)(T); -let x: Assert; // string +let assert: Assert; // string + +type Minus = ((v: U | B) => U)(A); +let noNumbers: Minus; // string + +interface UnwrapPromise { + (v: PromiseLike): UnwrapPromise(U); + (v: U): U; +}; +declare const testUnwrap1: UnwrapPromise(string); +declare const testUnwrap2: UnwrapPromise(Promise); +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +declare function myThen( + prom: Promise, + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +declare const pr: Promise; +declare function f(x: number): Promise; +declare function g(x: number): number | Promise; +const testThen = myThen(pr, f, g); + +interface Promise { + then( + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +} +// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter +// of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { + if (x < 0) return f(x); + return x; +}); interface ObjectHasStringIndex { // (o: T): T[string]; From ccc55d13bd9f57493e7e833e0f7dc5143a1c0512 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Mon, 11 Sep 2017 18:06:32 +0800 Subject: [PATCH 20/25] add tests --- tests/baselines/reference/typeCall.js | 39 ++- tests/baselines/reference/typeCall.symbols | 288 ++++++++++++++------- tests/baselines/reference/typeCall.types | 99 +++++++ tests/cases/compiler/typeCall.ts | 26 +- 4 files changed, 349 insertions(+), 103 deletions(-) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index d2c321b43afe6..9fe2028e69ad5 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -41,6 +41,29 @@ type genericIsPrimitive3 = (v: T) => IsPrimitive(T); type stringIsPrimitive3 = genericIsPrimitive3(string); type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) + +interface BoolToString { + (v: false): 'false'; + (v: true): 'true'; +} +type strTrue = BoolToString(true); +type strFalse = BoolToString(false); +type strEither = BoolToString(true | false); +type strBool = BoolToString(boolean); +type strAny = BoolToString(any); + +declare function safeDivide< + B extends number, + NotZero = ((v: '1') => 'whatever')({ + (v: 0): '0'; + (v: number): '1'; + }(B)) +>(a: number, b: B): number; +safeDivide(3, 1); +safeDivide(3, 0); // fails, should error but doesn't + type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); @@ -136,8 +159,7 @@ interface Promise { onrejected?: ((reason: any) => TResult2) | undefined | null ): Promise; } -// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter -// of type '(value: number) => string | PromiseLike'; +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; const tryProm = pr.then((x: number) => { if (x < 0) return f(x); return x; @@ -241,6 +263,16 @@ function comparability(x: T, y: () => T) { //// [typeCall.js] var a = 'foo'; +angularFactory(function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return function (foo) { return [foo]; }; +}); +safeDivide(3, 1); +safeDivide(3, 0); // fails, should error but doesn't +var z = map(function (v) { return [v]; }, { a: 1, b: 2, c: 3 }); var obj = null; var keys = null; var pathTest = path(obj, keys); @@ -261,8 +293,7 @@ var assert; // string var noNumbers; // string ; var testThen = myThen(pr, f, g); -// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter -// of type '(value: number) => string | PromiseLike'; +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; var tryProm = pr.then(function (x) { if (x < 0) return f(x); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 6d28a8da46b00..65dc4440e75b5 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -116,130 +116,224 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) >genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 35, 45)) >RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +>angularFactory : Symbol(angularFactory, Decl(typeCall.ts, 40, 53)) +>G : Symbol(G, Decl(typeCall.ts, 42, 32)) +>args : Symbol(args, Decl(typeCall.ts, 42, 43)) +>R : Symbol(R, Decl(typeCall.ts, 42, 64)) +>R : Symbol(R, Decl(typeCall.ts, 42, 64)) +>T : Symbol(T, Decl(typeCall.ts, 42, 76)) +>foo : Symbol(foo, Decl(typeCall.ts, 42, 79)) +>T : Symbol(T, Decl(typeCall.ts, 42, 76)) +>T : Symbol(T, Decl(typeCall.ts, 42, 76)) +>g : Symbol(g, Decl(typeCall.ts, 42, 95)) +>G : Symbol(G, Decl(typeCall.ts, 42, 32)) +>R : Symbol(R, Decl(typeCall.ts, 42, 64)) + +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) +>angularFactory : Symbol(angularFactory, Decl(typeCall.ts, 40, 53)) +>args : Symbol(args, Decl(typeCall.ts, 43, 16)) +>T : Symbol(T, Decl(typeCall.ts, 43, 36)) +>foo : Symbol(foo, Decl(typeCall.ts, 43, 39)) +>T : Symbol(T, Decl(typeCall.ts, 43, 36)) +>foo : Symbol(foo, Decl(typeCall.ts, 43, 39)) +>T : Symbol(T, Decl(typeCall.ts, 43, 36)) + +interface BoolToString { +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + + (v: false): 'false'; +>v : Symbol(v, Decl(typeCall.ts, 46, 5)) + + (v: true): 'true'; +>v : Symbol(v, Decl(typeCall.ts, 47, 5)) +} +type strTrue = BoolToString(true); +>strTrue : Symbol(strTrue, Decl(typeCall.ts, 48, 1)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strFalse = BoolToString(false); +>strFalse : Symbol(strFalse, Decl(typeCall.ts, 49, 34)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strEither = BoolToString(true | false); +>strEither : Symbol(strEither, Decl(typeCall.ts, 50, 36)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strBool = BoolToString(boolean); +>strBool : Symbol(strBool, Decl(typeCall.ts, 51, 44), Decl(typeCall.ts, 124, 3)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strAny = BoolToString(any); +>strAny : Symbol(strAny, Decl(typeCall.ts, 52, 37)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +declare function safeDivide< +>safeDivide : Symbol(safeDivide, Decl(typeCall.ts, 53, 32)) + + B extends number, +>B : Symbol(B, Decl(typeCall.ts, 55, 28)) + + NotZero = ((v: '1') => 'whatever')({ +>NotZero : Symbol(NotZero, Decl(typeCall.ts, 56, 19)) +>v : Symbol(v, Decl(typeCall.ts, 57, 14)) + + (v: 0): '0'; +>v : Symbol(v, Decl(typeCall.ts, 58, 5)) + + (v: number): '1'; +>v : Symbol(v, Decl(typeCall.ts, 59, 5)) + + }(B)) +>B : Symbol(B, Decl(typeCall.ts, 55, 28)) + +>(a: number, b: B): number; +>a : Symbol(a, Decl(typeCall.ts, 61, 2)) +>b : Symbol(b, Decl(typeCall.ts, 61, 12)) +>B : Symbol(B, Decl(typeCall.ts, 55, 28)) + +safeDivide(3, 1); +>safeDivide : Symbol(safeDivide, Decl(typeCall.ts, 53, 32)) + +safeDivide(3, 0); // fails, should error but doesn't +>safeDivide : Symbol(safeDivide, Decl(typeCall.ts, 53, 32)) + type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; ->map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 42, 12)) ->v : Symbol(v, Decl(typeCall.ts, 42, 24)) ->T : Symbol(T, Decl(typeCall.ts, 42, 67)) ->O : Symbol(O, Decl(typeCall.ts, 42, 37)) ->k : Symbol(k, Decl(typeCall.ts, 42, 51)) ->T : Symbol(T, Decl(typeCall.ts, 42, 67)) ->T : Symbol(T, Decl(typeCall.ts, 42, 67)) ->fn : Symbol(fn, Decl(typeCall.ts, 42, 71)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 42, 12)) ->obj : Symbol(obj, Decl(typeCall.ts, 42, 78)) ->O : Symbol(O, Decl(typeCall.ts, 42, 37)) ->P : Symbol(P, Decl(typeCall.ts, 42, 93)) ->O : Symbol(O, Decl(typeCall.ts, 42, 37)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 42, 12)) ->O : Symbol(O, Decl(typeCall.ts, 42, 37)) ->P : Symbol(P, Decl(typeCall.ts, 42, 93)) +>map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 65, 12)) +>v : Symbol(v, Decl(typeCall.ts, 65, 24)) +>T : Symbol(T, Decl(typeCall.ts, 65, 67)) +>O : Symbol(O, Decl(typeCall.ts, 65, 37)) +>k : Symbol(k, Decl(typeCall.ts, 65, 51)) +>T : Symbol(T, Decl(typeCall.ts, 65, 67)) +>T : Symbol(T, Decl(typeCall.ts, 65, 67)) +>fn : Symbol(fn, Decl(typeCall.ts, 65, 71)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 65, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 65, 78)) +>O : Symbol(O, Decl(typeCall.ts, 65, 37)) +>P : Symbol(P, Decl(typeCall.ts, 65, 93)) +>O : Symbol(O, Decl(typeCall.ts, 65, 37)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 65, 12)) +>O : Symbol(O, Decl(typeCall.ts, 65, 37)) +>P : Symbol(P, Decl(typeCall.ts, 65, 93)) type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : Symbol(z, Decl(typeCall.ts, 42, 119)) ->map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) ->T : Symbol(T, Decl(typeCall.ts, 43, 14)) ->v : Symbol(v, Decl(typeCall.ts, 43, 17)) ->T : Symbol(T, Decl(typeCall.ts, 43, 14)) ->T : Symbol(T, Decl(typeCall.ts, 43, 14)) ->a : Symbol(a, Decl(typeCall.ts, 43, 32)) ->b : Symbol(b, Decl(typeCall.ts, 43, 38)) ->c : Symbol(c, Decl(typeCall.ts, 43, 44)) +>z : Symbol(z, Decl(typeCall.ts, 65, 119), Decl(typeCall.ts, 68, 3)) +>map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) +>T : Symbol(T, Decl(typeCall.ts, 66, 14)) +>v : Symbol(v, Decl(typeCall.ts, 66, 17)) +>T : Symbol(T, Decl(typeCall.ts, 66, 14)) +>T : Symbol(T, Decl(typeCall.ts, 66, 14)) +>a : Symbol(a, Decl(typeCall.ts, 66, 32)) +>b : Symbol(b, Decl(typeCall.ts, 66, 38)) +>c : Symbol(c, Decl(typeCall.ts, 66, 44)) declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); ->map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 44, 21)) ->v : Symbol(v, Decl(typeCall.ts, 44, 33)) ->T : Symbol(T, Decl(typeCall.ts, 44, 76)) ->O : Symbol(O, Decl(typeCall.ts, 44, 46)) ->k : Symbol(k, Decl(typeCall.ts, 44, 60)) ->T : Symbol(T, Decl(typeCall.ts, 44, 76)) ->T : Symbol(T, Decl(typeCall.ts, 44, 76)) ->fn : Symbol(fn, Decl(typeCall.ts, 44, 80)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 44, 21)) ->obj : Symbol(obj, Decl(typeCall.ts, 44, 87)) ->O : Symbol(O, Decl(typeCall.ts, 44, 46)) ->map : Symbol(map, Decl(typeCall.ts, 40, 53), Decl(typeCall.ts, 43, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 44, 21)) ->O : Symbol(O, Decl(typeCall.ts, 44, 46)) - -// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain +>map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 67, 21)) +>v : Symbol(v, Decl(typeCall.ts, 67, 33)) +>T : Symbol(T, Decl(typeCall.ts, 67, 76)) +>O : Symbol(O, Decl(typeCall.ts, 67, 46)) +>k : Symbol(k, Decl(typeCall.ts, 67, 60)) +>T : Symbol(T, Decl(typeCall.ts, 67, 76)) +>T : Symbol(T, Decl(typeCall.ts, 67, 76)) +>fn : Symbol(fn, Decl(typeCall.ts, 67, 80)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 67, 21)) +>obj : Symbol(obj, Decl(typeCall.ts, 67, 87)) +>O : Symbol(O, Decl(typeCall.ts, 67, 46)) +>map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 67, 21)) +>O : Symbol(O, Decl(typeCall.ts, 67, 46)) + +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); +>z : Symbol(z, Decl(typeCall.ts, 65, 119), Decl(typeCall.ts, 68, 3)) +>map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) +>T : Symbol(T, Decl(typeCall.ts, 68, 13)) +>v : Symbol(v, Decl(typeCall.ts, 68, 16)) +>T : Symbol(T, Decl(typeCall.ts, 68, 13)) +>v : Symbol(v, Decl(typeCall.ts, 68, 16)) +>T : Symbol(T, Decl(typeCall.ts, 68, 13)) +>a : Symbol(a, Decl(typeCall.ts, 68, 38)) +>b : Symbol(b, Decl(typeCall.ts, 68, 44)) +>c : Symbol(c, Decl(typeCall.ts, 68, 50)) +>a : Symbol(a, Decl(typeCall.ts, 68, 62)) +>b : Symbol(b, Decl(typeCall.ts, 68, 68)) +>c : Symbol(c, Decl(typeCall.ts, 68, 74)) type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; ->Inc : Symbol(Inc, Decl(typeCall.ts, 44, 108)) ->k : Symbol(k, Decl(typeCall.ts, 48, 14)) +>Inc : Symbol(Inc, Decl(typeCall.ts, 68, 83)) +>k : Symbol(k, Decl(typeCall.ts, 70, 14)) type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; ->StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 48, 98)) ->k : Symbol(k, Decl(typeCall.ts, 49, 25)) +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 70, 98)) +>k : Symbol(k, Decl(typeCall.ts, 71, 25)) type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; ->TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 49, 82)) ->Arr : Symbol(Arr, Decl(typeCall.ts, 50, 19)) ->I : Symbol(I, Decl(typeCall.ts, 50, 37)) ->K : Symbol(K, Decl(typeCall.ts, 50, 61)) ->Arr : Symbol(Arr, Decl(typeCall.ts, 50, 19)) ->k : Symbol(k, Decl(typeCall.ts, 50, 89)) ->I : Symbol(I, Decl(typeCall.ts, 50, 37)) +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 71, 82)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 72, 19)) +>I : Symbol(I, Decl(typeCall.ts, 72, 37)) +>K : Symbol(K, Decl(typeCall.ts, 72, 61)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 72, 19)) +>k : Symbol(k, Decl(typeCall.ts, 72, 89)) +>I : Symbol(I, Decl(typeCall.ts, 72, 37)) type PathFn, I extends string = '0'> = ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) ->T : Symbol(T, Decl(typeCall.ts, 51, 12)) ->k : Symbol(k, Decl(typeCall.ts, 51, 25)) ->R : Symbol(R, Decl(typeCall.ts, 51, 43)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) +>T : Symbol(T, Decl(typeCall.ts, 73, 12)) +>k : Symbol(k, Decl(typeCall.ts, 73, 25)) +>R : Symbol(R, Decl(typeCall.ts, 73, 43)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->I : Symbol(I, Decl(typeCall.ts, 51, 68)) +>I : Symbol(I, Decl(typeCall.ts, 73, 68)) { 1: PathFn, 0: T }[TupleHasIndex]; ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) ->T : Symbol(T, Decl(typeCall.ts, 51, 12)) ->R : Symbol(R, Decl(typeCall.ts, 51, 43)) ->StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 48, 98)) ->I : Symbol(I, Decl(typeCall.ts, 51, 68)) ->R : Symbol(R, Decl(typeCall.ts, 51, 43)) ->Inc : Symbol(Inc, Decl(typeCall.ts, 44, 108)) ->I : Symbol(I, Decl(typeCall.ts, 51, 68)) ->T : Symbol(T, Decl(typeCall.ts, 51, 12)) ->TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 49, 82)) ->R : Symbol(R, Decl(typeCall.ts, 51, 43)) ->I : Symbol(I, Decl(typeCall.ts, 51, 68)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) +>T : Symbol(T, Decl(typeCall.ts, 73, 12)) +>R : Symbol(R, Decl(typeCall.ts, 73, 43)) +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 70, 98)) +>I : Symbol(I, Decl(typeCall.ts, 73, 68)) +>R : Symbol(R, Decl(typeCall.ts, 73, 43)) +>Inc : Symbol(Inc, Decl(typeCall.ts, 68, 83)) +>I : Symbol(I, Decl(typeCall.ts, 73, 68)) +>T : Symbol(T, Decl(typeCall.ts, 73, 12)) +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 71, 82)) +>R : Symbol(R, Decl(typeCall.ts, 73, 43)) +>I : Symbol(I, Decl(typeCall.ts, 73, 68)) type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; ->PathTest : Symbol(PathTest, Decl(typeCall.ts, 52, 81)) ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) ->a : Symbol(a, Decl(typeCall.ts, 53, 24)) ->b : Symbol(b, Decl(typeCall.ts, 53, 29)) ->d : Symbol(d, Decl(typeCall.ts, 53, 40)) +>PathTest : Symbol(PathTest, Decl(typeCall.ts, 74, 81)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) +>a : Symbol(a, Decl(typeCall.ts, 75, 24)) +>b : Symbol(b, Decl(typeCall.ts, 75, 29)) +>d : Symbol(d, Decl(typeCall.ts, 75, 40)) declare function path>(obj: T, path: R): PathFn; ->path : Symbol(path, Decl(typeCall.ts, 53, 78)) ->T : Symbol(T, Decl(typeCall.ts, 54, 22)) ->k : Symbol(k, Decl(typeCall.ts, 54, 35)) ->R : Symbol(R, Decl(typeCall.ts, 54, 53)) +>path : Symbol(path, Decl(typeCall.ts, 75, 78)) +>T : Symbol(T, Decl(typeCall.ts, 76, 22)) +>k : Symbol(k, Decl(typeCall.ts, 76, 35)) +>R : Symbol(R, Decl(typeCall.ts, 76, 53)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->obj : Symbol(obj, Decl(typeCall.ts, 54, 79)) ->T : Symbol(T, Decl(typeCall.ts, 54, 22)) ->path : Symbol(path, Decl(typeCall.ts, 54, 86)) ->R : Symbol(R, Decl(typeCall.ts, 54, 53)) ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 50, 111)) ->T : Symbol(T, Decl(typeCall.ts, 54, 22)) ->R : Symbol(R, Decl(typeCall.ts, 54, 53)) +>obj : Symbol(obj, Decl(typeCall.ts, 76, 79)) +>T : Symbol(T, Decl(typeCall.ts, 76, 22)) +>path : Symbol(path, Decl(typeCall.ts, 76, 86)) +>R : Symbol(R, Decl(typeCall.ts, 76, 53)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) +>T : Symbol(T, Decl(typeCall.ts, 76, 22)) +>R : Symbol(R, Decl(typeCall.ts, 76, 53)) const obj = null! as { a: { b: ['c', { d: 'e' }] } }; ->obj : Symbol(obj, Decl(typeCall.ts, 55, 5)) ->a : Symbol(a, Decl(typeCall.ts, 55, 22)) ->b : Symbol(b, Decl(typeCall.ts, 55, 27)) ->d : Symbol(d, Decl(typeCall.ts, 55, 38)) +>obj : Symbol(obj, Decl(typeCall.ts, 77, 5)) +>a : Symbol(a, Decl(typeCall.ts, 77, 22)) +>b : Symbol(b, Decl(typeCall.ts, 77, 27)) +>d : Symbol(d, Decl(typeCall.ts, 77, 38)) const keys = null! as ['a', 'b', '1', 'd']; ->keys : Symbol(keys, Decl(typeCall.ts, 56, 5)) +>keys : Symbol(keys, Decl(typeCall.ts, 78, 5)) const pathTest = path(obj, keys); ->pathTest : Symbol(pathTest, Decl(typeCall.ts, 57, 5)) ->path : Symbol(path, Decl(typeCall.ts, 53, 78)) ->obj : Symbol(obj, Decl(typeCall.ts, 55, 5)) ->keys : Symbol(keys, Decl(typeCall.ts, 56, 5)) +>pathTest : Symbol(pathTest, Decl(typeCall.ts, 79, 5)) +>path : Symbol(path, Decl(typeCall.ts, 75, 78)) +>obj : Symbol(obj, Decl(typeCall.ts, 77, 5)) +>keys : Symbol(keys, Decl(typeCall.ts, 78, 5)) // "e" diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index ae3f434d3018d..647fbef2703bf 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -117,6 +117,105 @@ type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) >genericIsPrimitive3 : genericIsPrimitive3 >RegExp : RegExp +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +>angularFactory : R, R extends (foo: T) => T[]>(g: G) => R(123) +>G : G +>args : any[] +>R : R +>R : R +>T : T +>foo : T +>T : T +>T : T +>g : G +>G : G +>R : R + +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) +>angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) : 123[] +>angularFactory : R, R extends (foo: T) => T[]>(g: G) => R(123) +>(...args: any[]) => (foo: T) => [foo] as [T] : (...args: any[]) => (foo: T) => [T] +>args : any[] +>(foo: T) => [foo] as [T] : (foo: T) => [T] +>T : T +>foo : T +>T : T +>[foo] as [T] : [T] +>[foo] : [T] +>foo : T +>T : T + +interface BoolToString { +>BoolToString : BoolToString + + (v: false): 'false'; +>v : false +>false : false + + (v: true): 'true'; +>v : true +>true : true +} +type strTrue = BoolToString(true); +>strTrue : "true" +>BoolToString : BoolToString +>true : true + +type strFalse = BoolToString(false); +>strFalse : "false" +>BoolToString : BoolToString +>false : false + +type strEither = BoolToString(true | false); +>strEither : any +>BoolToString : BoolToString +>true : true +>false : false + +type strBool = BoolToString(boolean); +>strBool : any +>BoolToString : BoolToString + +type strAny = BoolToString(any); +>strAny : any +>BoolToString : BoolToString + +declare function safeDivide< +>safeDivide : "whatever")({ (v: 0): "0"; (v: number): "1"; }(B))>(a: number, b: B) => number + + B extends number, +>B : B + + NotZero = ((v: '1') => 'whatever')({ +>NotZero : NotZero +>v : "1" + + (v: 0): '0'; +>v : 0 + + (v: number): '1'; +>v : number + + }(B)) +>B : B + +>(a: number, b: B): number; +>a : number +>b : B +>B : B + +safeDivide(3, 1); +>safeDivide(3, 1) : number +>safeDivide : "whatever")({ (v: 0): "0"; (v: number): "1"; }(B))>(a: number, b: B) => number +>3 : 3 +>1 : 1 + +safeDivide(3, 0); // fails, should error but doesn't +>safeDivide(3, 0) : number +>safeDivide : "whatever")({ (v: 0): "0"; (v: number): "1"; }(B))>(a: number, b: B) => number +>3 : 3 +>0 : 0 + type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; >map : map >Fn : Fn diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 2d18c5864e25a..8ab2bdb444dc6 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -44,6 +44,29 @@ type genericIsPrimitive3 = (v: T) => IsPrimitive(T); type stringIsPrimitive3 = genericIsPrimitive3(string); type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) + +interface BoolToString { + (v: false): 'false'; + (v: true): 'true'; +} +type strTrue = BoolToString(true); +type strFalse = BoolToString(false); +type strEither = BoolToString(true | false); +type strBool = BoolToString(boolean); +type strAny = BoolToString(any); + +declare function safeDivide< + B extends number, + NotZero = ((v: '1') => 'whatever')({ + (v: 0): '0'; + (v: number): '1'; + }(B)) +>(a: number, b: B): number; +safeDivide(3, 1); +safeDivide(3, 0); // fails, should error but doesn't + type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); @@ -139,8 +162,7 @@ interface Promise { onrejected?: ((reason: any) => TResult2) | undefined | null ): Promise; } -// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter -// of type '(value: number) => string | PromiseLike'; +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; const tryProm = pr.then((x: number) => { if (x < 0) return f(x); return x; From a7882c2c56d85a7811fc8b59f959400c9fe8f2a7 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Mon, 11 Sep 2017 18:19:48 +0800 Subject: [PATCH 21/25] add error tests in own file --- .../reference/typeCallErrors.errors.txt | 32 +++++++++++++++++++ tests/baselines/reference/typeCallErrors.js | 29 +++++++++++++++++ tests/cases/compiler/typeCall.ts | 9 ------ tests/cases/compiler/typeCallErrors.ts | 16 ++++++++++ 4 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 tests/baselines/reference/typeCallErrors.errors.txt create mode 100644 tests/baselines/reference/typeCallErrors.js create mode 100644 tests/cases/compiler/typeCallErrors.ts diff --git a/tests/baselines/reference/typeCallErrors.errors.txt b/tests/baselines/reference/typeCallErrors.errors.txt new file mode 100644 index 0000000000000..8e4e2510a1bd5 --- /dev/null +++ b/tests/baselines/reference/typeCallErrors.errors.txt @@ -0,0 +1,32 @@ +tests/cases/compiler/typeCallErrors.ts(8,16): error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. +tests/cases/compiler/typeCallErrors.ts(9,17): error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. +tests/cases/compiler/typeCallErrors.ts(10,18): error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. +tests/cases/compiler/typeCallErrors.ts(15,5): error TS2365: Operator '===' cannot be applied to types 'T' and '() => T'. + + +==== tests/cases/compiler/typeCallErrors.ts (4 errors) ==== + // binary function composition + type Fn1 = (v1: T1[]) => { [k: string]: T1 }; + type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; + let fn1 = null! as Fn1; + let fn2 = null! as Fn2; + type Fn3 = (v3: T3) => Fn2(Fn1(T3)); + let ones = null! as 1[]; + type Fn4 = Fn3(1); // errors, ok + ~ +!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. + let x = fn2(fn1(1)); // errors with not assignable, ok + ~ +!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. + type X = Fn2(Fn1(1)); // errors with not assignable, ok + ~ +!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. + + function comparability(x: T, y: () => T) { + x === x; + y === y; + x === y; // rightfully errors + ~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'T' and '() => T'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeCallErrors.js b/tests/baselines/reference/typeCallErrors.js new file mode 100644 index 0000000000000..7f1c66a0c74af --- /dev/null +++ b/tests/baselines/reference/typeCallErrors.js @@ -0,0 +1,29 @@ +//// [typeCallErrors.ts] +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +let ones = null! as 1[]; +type Fn4 = Fn3(1); // errors, ok +let x = fn2(fn1(1)); // errors with not assignable, ok +type X = Fn2(Fn1(1)); // errors with not assignable, ok + +function comparability(x: T, y: () => T) { + x === x; + y === y; + x === y; // rightfully errors +} + + +//// [typeCallErrors.js] +var fn1 = null; +var fn2 = null; +var ones = null; +var x = fn2(fn1(1)); // errors with not assignable, ok +function comparability(x, y) { + x === x; + y === y; + x === y; // rightfully errors +} diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 8ab2bdb444dc6..a7f5a1f5b8a49 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -109,14 +109,11 @@ type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; let fn1 = null! as Fn1; let fn2 = null! as Fn2; type Fn3 = (v3: T3) => Fn2(Fn1(T3)); -// type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; type Fn4b = Fn3(typeof ones); // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. -// let x = fn2(fn1(1)); // errors with not assignable, ok -// type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); type Y = Fn2(Fn1(1[])); @@ -234,12 +231,6 @@ function assignability(x: T, y: () => T) { const b: T = y(); } -function comparability(x: T, y: () => T) { - x === x; - y === y; - // x === y; // rightfully errors -} - // function mappedAssignability(x: T, y: CallMember) { // const d: T() = y; // } diff --git a/tests/cases/compiler/typeCallErrors.ts b/tests/cases/compiler/typeCallErrors.ts new file mode 100644 index 0000000000000..e83a3d0183567 --- /dev/null +++ b/tests/cases/compiler/typeCallErrors.ts @@ -0,0 +1,16 @@ +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +let ones = null! as 1[]; +type Fn4 = Fn3(1); // errors, ok +let x = fn2(fn1(1)); // errors with not assignable, ok +type X = Fn2(Fn1(1)); // errors with not assignable, ok + +function comparability(x: T, y: () => T) { + x === x; + y === y; + x === y; // rightfully errors +} From e67a82bffecd5952ec8efb3aa39975f4e540d095 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Mon, 11 Sep 2017 19:47:44 +0800 Subject: [PATCH 22/25] simplify out unused bits --- src/compiler/checker.ts | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 420257c0532f4..12174cd647d05 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7588,28 +7588,8 @@ namespace ts { const args = type.arguments; const calls = getSignaturesOfType(fn, SignatureKind.Call); const sig = resolveCall(node, calls, []); - if (!sig.typeParameters || !sig.typeParameters.length) { - return getReturnTypeOfSignature(sig); - } - const inferenceContext = createInferenceContext(sig, InferenceFlags.InferUnionTypes); - const types = inferTypeArgumentsForTypeCall(sig, args, inferenceContext); // TODO: add Fn(this: A, B, C) syntax - const signature = getSignatureInstantiation(sig, types); - return getReturnTypeOfSignature(signature); - } - - function inferTypeArgumentsForTypeCall(signature: Signature, args: Type[], context: InferenceContext, thisArgumentType?: Type): Type[] { - const thisType = getThisTypeOfSignature(signature); - if (thisType) { - inferTypes(context.inferences || [], thisArgumentType, thisType); - } - const argCount = args.length; - for (let i = 0; i < argCount; i++) { - const paramType = getTypeAtPosition(signature, i); - const argType = args[i]; - inferTypes(context.inferences || [], argType, paramType); - } - return getInferredTypes(context); - } + return sig ? getReturnTypeOfSignature(sig) : unknownType; + } function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { const links = getNodeLinks(node); From 5decbbc154df15769829de51642e19b4b6199192 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Mon, 11 Sep 2017 21:17:38 +0800 Subject: [PATCH 23/25] directly pass arg types for type calls, fixes compose --- src/compiler/checker.ts | 44 +- src/compiler/types.ts | 1 + tests/baselines/reference/typeCall.js | 47 +- tests/baselines/reference/typeCall.symbols | 926 ++++++++++----------- tests/baselines/reference/typeCall.types | 117 ++- tests/cases/compiler/typeCall.ts | 28 +- 6 files changed, 548 insertions(+), 615 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 12174cd647d05..6ee4b12110133 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5933,8 +5933,8 @@ namespace ts { function getConstraintOfTypeCall(type: TypeCallType): Type { const fn = type.function; const args = map(type.arguments, getConstraintOfType); - const call = createTypeCallType(fn, args); - return getTypeFromTypeCall(call); + const call = createTypeCallType(fn, args, type.node); + return getTypeFromTypeCall(call, type.node); } function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type { @@ -7568,26 +7568,27 @@ namespace ts { false; } - function createTypeCallType(fn: Type, args: Type[]): TypeCallType { + function createTypeCallType(fn: Type, args: Type[], node: TypeCallTypeNode): TypeCallType { const type = createType(TypeFlags.TypeCall); type.function = fn; type.arguments = args; + type.node = node; return type; } - function getTypeCallType(fn: Type, args: Type[], node?: TypeCallTypeNode): Type { - const type = createTypeCallType(fn, args); + function getTypeCallType(fn: Type, args: Type[], node: TypeCallTypeNode): Type { + const type = createTypeCallType(fn, args, node); if (isGenericTypeCallType(fn) || some(args, isGenericTypeCallType)) { return type; } return getTypeFromTypeCall(type, node); } - function getTypeFromTypeCall(type: TypeCallType, node = nodeBuilder.typeToTypeNode(type)): Type { + function getTypeFromTypeCall(type: TypeCallType, node: TypeCallTypeNode): Type { const fn = type.function; const args = type.arguments; const calls = getSignaturesOfType(fn, SignatureKind.Call); - const sig = resolveCall(node, calls, []); + const sig = resolveCall(node, calls, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, args); return sig ? getReturnTypeOfSignature(sig) : unknownType; } @@ -7603,7 +7604,6 @@ namespace ts { return links.resolvedType; } - function createIndexedAccessType(objectType: Type, indexType: Type) { const type = createType(TypeFlags.IndexedAccess); type.objectType = objectType; @@ -8418,9 +8418,12 @@ namespace ts { return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); } if (type.flags & TypeFlags.TypeCall) { + const typeCallNode = nodeBuilder.typeToTypeNode(type); + typeCallNode.parent = (type as TypeCallType).node; return getTypeCallType( instantiateType((type).function, mapper), - instantiateTypes((type).arguments, mapper) + instantiateTypes((type).arguments, mapper), + typeCallNode ); } return type; @@ -15297,7 +15300,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLike, signature: Signature, args: Arguments, excludeArgument: boolean[], context: InferenceContext): Type[] { + function inferTypeArguments(node: CallLike, signature: Signature, args: Arguments, excludeArgument: boolean[], context: InferenceContext, argTypes?: Type[]): Type[] { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (const inference of context.inferences) { // As an optimization, we don't have to clear (and later recompute) inferred types @@ -15352,7 +15355,7 @@ namespace ts { // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. if (isTypeCallTypeNode(node) || arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - let argType = getEffectiveArgumentType(node, i); + let argType = argTypes ? argTypes[i] : getEffectiveArgumentType(node, i); // If the effective argument type is 'undefined', there is no synthetic type // for the argument. In that case, we should check the argument. @@ -15455,7 +15458,8 @@ namespace ts { signature: Signature, relation: Map, excludeArgument: boolean[], - reportErrors: boolean) { + reportErrors: boolean, + argTypes: Type[]) { if (isJsxOpeningLikeElement(node)) { return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation); } @@ -15465,7 +15469,7 @@ namespace ts { // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. // If the expression is a new expression, then the check is skipped. const thisArgumentNode = getThisArgumentOfCall(node); - const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; + const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; // type calls: TODO const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1; if (!checkTypeRelatedTo(thisArgumentType, getThisTypeOfSignature(signature), relation, errorNode, headMessage)) { @@ -15482,7 +15486,7 @@ namespace ts { const paramType = getTypeAtPosition(signature, i); // If the effective argument type is undefined, there is no synthetic type for the argument. // In that case, we should check the argument. - const argType = getEffectiveArgumentType(node, i) || + const argType = argTypes ? argTypes[i] : getEffectiveArgumentType(node, i) || checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete @@ -15820,11 +15824,11 @@ namespace ts { return (node).template; } else { - return arg; + return arg || node; } } - function resolveCall(node: CallLike, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage): Signature { + function resolveCall(node: CallLike, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage, argTypes?: Type[]): Signature { const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; const isDecorator = node.kind === SyntaxKind.Decorator; const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); @@ -15945,7 +15949,7 @@ namespace ts { // in arguments too early. If possible, we'd like to only type them once we know the correct // overload. However, this matters for the case where the call is correct. When the call is // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true, argTypes); } else if (candidateForTypeArgumentError) { const typeArguments = (node).typeArguments; @@ -16026,7 +16030,7 @@ namespace ts { if (!hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false, argTypes)) { candidateForArgumentError = candidate; return undefined; } @@ -16056,11 +16060,11 @@ namespace ts { } } else { - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext, argTypes); } candidate = getSignatureInstantiation(candidate, typeArgumentTypes); } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false, argTypes)) { candidateForArgumentError = candidate; break; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ce31fb38274af..bb33200b8f5a6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3416,6 +3416,7 @@ namespace ts { export interface TypeCallType extends TypeVariable { function: Type; arguments: Type[]; + node: TypeCallTypeNode; } // keyof T types (TypeFlags.Index) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 9fe2028e69ad5..a7eaa7e839c88 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -45,30 +45,32 @@ declare function angularFactory R, R extends (f angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) interface BoolToString { + (v: false & true): never; (v: false): 'false'; (v: true): 'true'; + (v: boolean): 'true' | 'false'; } type strTrue = BoolToString(true); type strFalse = BoolToString(false); type strEither = BoolToString(true | false); type strBool = BoolToString(boolean); -type strAny = BoolToString(any); - -declare function safeDivide< - B extends number, - NotZero = ((v: '1') => 'whatever')({ - (v: 0): '0'; - (v: number): '1'; - }(B)) ->(a: number, b: B): number; -safeDivide(3, 1); -safeDivide(3, 0); // fails, should error but doesn't +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' + +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); -// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; @@ -106,14 +108,11 @@ type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; let fn1 = null! as Fn1; let fn2 = null! as Fn2; type Fn3 = (v3: T3) => Fn2(Fn1(T3)); -// type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; type Fn4b = Fn3(typeof ones); // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. -// let x = fn2(fn1(1)); // errors with not assignable, ok -// type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); type Y = Fn2(Fn1(1[])); @@ -231,12 +230,6 @@ function assignability(x: T, y: () => T) { const b: T = y(); } -function comparability(x: T, y: () => T) { - x === x; - y === y; - // x === y; // rightfully errors -} - // function mappedAssignability(x: T, y: CallMember) { // const d: T() = y; // } @@ -270,19 +263,14 @@ angularFactory(function () { } return function (foo) { return [foo]; }; }); -safeDivide(3, 1); -safeDivide(3, 0); // fails, should error but doesn't var z = map(function (v) { return [v]; }, { a: 1, b: 2, c: 3 }); var obj = null; var keys = null; var pathTest = path(obj, keys); var fn1 = null; var fn2 = null; -// type Fn4 = Fn3(1); // errors, ok var ones = null; // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. -// let x = fn2(fn1(1)); // errors with not assignable, ok -// type X = Fn2(Fn1(1)); // errors with not assignable, ok var y = fn2(fn1(ones)); var falseBool; // 1 var trueBool; // 1 @@ -313,11 +301,6 @@ function assignability(x, y) { var a = x; var b = y(); } -function comparability(x, y) { - x === x; - y === y; - // x === y; // rightfully errors -} // function mappedAssignability(x: T, y: CallMember) { // const d: T() = y; // } diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 65dc4440e75b5..01db619a96aa5 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -44,12 +44,12 @@ let a = 'foo'; >a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) type f = typeof f4(typeof a); ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) >f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) >a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) type g = (() => 1)(); ->g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 127, 47)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 149, 47)) type Id = (v: T) => T; >Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) @@ -142,198 +142,185 @@ angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) interface BoolToString { >BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) - (v: false): 'false'; + (v: false & true): never; >v : Symbol(v, Decl(typeCall.ts, 46, 5)) - (v: true): 'true'; + (v: false): 'false'; >v : Symbol(v, Decl(typeCall.ts, 47, 5)) + + (v: true): 'true'; +>v : Symbol(v, Decl(typeCall.ts, 48, 5)) + + (v: boolean): 'true' | 'false'; +>v : Symbol(v, Decl(typeCall.ts, 49, 5)) } type strTrue = BoolToString(true); ->strTrue : Symbol(strTrue, Decl(typeCall.ts, 48, 1)) +>strTrue : Symbol(strTrue, Decl(typeCall.ts, 50, 1)) >BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) type strFalse = BoolToString(false); ->strFalse : Symbol(strFalse, Decl(typeCall.ts, 49, 34)) +>strFalse : Symbol(strFalse, Decl(typeCall.ts, 51, 34)) >BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) type strEither = BoolToString(true | false); ->strEither : Symbol(strEither, Decl(typeCall.ts, 50, 36)) +>strEither : Symbol(strEither, Decl(typeCall.ts, 52, 36)) >BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) type strBool = BoolToString(boolean); ->strBool : Symbol(strBool, Decl(typeCall.ts, 51, 44), Decl(typeCall.ts, 124, 3)) +>strBool : Symbol(strBool, Decl(typeCall.ts, 53, 44), Decl(typeCall.ts, 126, 3)) >BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) -type strAny = BoolToString(any); ->strAny : Symbol(strAny, Decl(typeCall.ts, 52, 37)) +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' +>strAny : Symbol(strAny, Decl(typeCall.ts, 54, 37)) >BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) -declare function safeDivide< ->safeDivide : Symbol(safeDivide, Decl(typeCall.ts, 53, 32)) - - B extends number, ->B : Symbol(B, Decl(typeCall.ts, 55, 28)) - - NotZero = ((v: '1') => 'whatever')({ ->NotZero : Symbol(NotZero, Decl(typeCall.ts, 56, 19)) ->v : Symbol(v, Decl(typeCall.ts, 57, 14)) - - (v: 0): '0'; ->v : Symbol(v, Decl(typeCall.ts, 58, 5)) - - (v: number): '1'; ->v : Symbol(v, Decl(typeCall.ts, 59, 5)) - - }(B)) ->B : Symbol(B, Decl(typeCall.ts, 55, 28)) - ->(a: number, b: B): number; ->a : Symbol(a, Decl(typeCall.ts, 61, 2)) ->b : Symbol(b, Decl(typeCall.ts, 61, 12)) ->B : Symbol(B, Decl(typeCall.ts, 55, 28)) - -safeDivide(3, 1); ->safeDivide : Symbol(safeDivide, Decl(typeCall.ts, 53, 32)) - -safeDivide(3, 0); // fails, should error but doesn't ->safeDivide : Symbol(safeDivide, Decl(typeCall.ts, 53, 32)) +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; ->map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 65, 12)) ->v : Symbol(v, Decl(typeCall.ts, 65, 24)) ->T : Symbol(T, Decl(typeCall.ts, 65, 67)) ->O : Symbol(O, Decl(typeCall.ts, 65, 37)) ->k : Symbol(k, Decl(typeCall.ts, 65, 51)) ->T : Symbol(T, Decl(typeCall.ts, 65, 67)) ->T : Symbol(T, Decl(typeCall.ts, 65, 67)) ->fn : Symbol(fn, Decl(typeCall.ts, 65, 71)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 65, 12)) ->obj : Symbol(obj, Decl(typeCall.ts, 65, 78)) ->O : Symbol(O, Decl(typeCall.ts, 65, 37)) ->P : Symbol(P, Decl(typeCall.ts, 65, 93)) ->O : Symbol(O, Decl(typeCall.ts, 65, 37)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 65, 12)) ->O : Symbol(O, Decl(typeCall.ts, 65, 37)) ->P : Symbol(P, Decl(typeCall.ts, 65, 93)) +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 68, 12)) +>v : Symbol(v, Decl(typeCall.ts, 68, 24)) +>T : Symbol(T, Decl(typeCall.ts, 68, 67)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>k : Symbol(k, Decl(typeCall.ts, 68, 51)) +>T : Symbol(T, Decl(typeCall.ts, 68, 67)) +>T : Symbol(T, Decl(typeCall.ts, 68, 67)) +>fn : Symbol(fn, Decl(typeCall.ts, 68, 71)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 68, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 68, 78)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>P : Symbol(P, Decl(typeCall.ts, 68, 93)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 68, 12)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>P : Symbol(P, Decl(typeCall.ts, 68, 93)) type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); ->z : Symbol(z, Decl(typeCall.ts, 65, 119), Decl(typeCall.ts, 68, 3)) ->map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) ->T : Symbol(T, Decl(typeCall.ts, 66, 14)) ->v : Symbol(v, Decl(typeCall.ts, 66, 17)) ->T : Symbol(T, Decl(typeCall.ts, 66, 14)) ->T : Symbol(T, Decl(typeCall.ts, 66, 14)) ->a : Symbol(a, Decl(typeCall.ts, 66, 32)) ->b : Symbol(b, Decl(typeCall.ts, 66, 38)) ->c : Symbol(c, Decl(typeCall.ts, 66, 44)) +>z : Symbol(z, Decl(typeCall.ts, 68, 119), Decl(typeCall.ts, 71, 3)) +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>T : Symbol(T, Decl(typeCall.ts, 69, 14)) +>v : Symbol(v, Decl(typeCall.ts, 69, 17)) +>T : Symbol(T, Decl(typeCall.ts, 69, 14)) +>T : Symbol(T, Decl(typeCall.ts, 69, 14)) +>a : Symbol(a, Decl(typeCall.ts, 69, 32)) +>b : Symbol(b, Decl(typeCall.ts, 69, 38)) +>c : Symbol(c, Decl(typeCall.ts, 69, 44)) declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); ->map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 67, 21)) ->v : Symbol(v, Decl(typeCall.ts, 67, 33)) ->T : Symbol(T, Decl(typeCall.ts, 67, 76)) ->O : Symbol(O, Decl(typeCall.ts, 67, 46)) ->k : Symbol(k, Decl(typeCall.ts, 67, 60)) ->T : Symbol(T, Decl(typeCall.ts, 67, 76)) ->T : Symbol(T, Decl(typeCall.ts, 67, 76)) ->fn : Symbol(fn, Decl(typeCall.ts, 67, 80)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 67, 21)) ->obj : Symbol(obj, Decl(typeCall.ts, 67, 87)) ->O : Symbol(O, Decl(typeCall.ts, 67, 46)) ->map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) ->Fn : Symbol(Fn, Decl(typeCall.ts, 67, 21)) ->O : Symbol(O, Decl(typeCall.ts, 67, 46)) +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) +>v : Symbol(v, Decl(typeCall.ts, 70, 33)) +>T : Symbol(T, Decl(typeCall.ts, 70, 76)) +>O : Symbol(O, Decl(typeCall.ts, 70, 46)) +>k : Symbol(k, Decl(typeCall.ts, 70, 60)) +>T : Symbol(T, Decl(typeCall.ts, 70, 76)) +>T : Symbol(T, Decl(typeCall.ts, 70, 76)) +>fn : Symbol(fn, Decl(typeCall.ts, 70, 80)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) +>obj : Symbol(obj, Decl(typeCall.ts, 70, 87)) +>O : Symbol(O, Decl(typeCall.ts, 70, 46)) +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) +>O : Symbol(O, Decl(typeCall.ts, 70, 46)) let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); ->z : Symbol(z, Decl(typeCall.ts, 65, 119), Decl(typeCall.ts, 68, 3)) ->map : Symbol(map, Decl(typeCall.ts, 63, 17), Decl(typeCall.ts, 66, 53)) ->T : Symbol(T, Decl(typeCall.ts, 68, 13)) ->v : Symbol(v, Decl(typeCall.ts, 68, 16)) ->T : Symbol(T, Decl(typeCall.ts, 68, 13)) ->v : Symbol(v, Decl(typeCall.ts, 68, 16)) ->T : Symbol(T, Decl(typeCall.ts, 68, 13)) ->a : Symbol(a, Decl(typeCall.ts, 68, 38)) ->b : Symbol(b, Decl(typeCall.ts, 68, 44)) ->c : Symbol(c, Decl(typeCall.ts, 68, 50)) ->a : Symbol(a, Decl(typeCall.ts, 68, 62)) ->b : Symbol(b, Decl(typeCall.ts, 68, 68)) ->c : Symbol(c, Decl(typeCall.ts, 68, 74)) +>z : Symbol(z, Decl(typeCall.ts, 68, 119), Decl(typeCall.ts, 71, 3)) +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>T : Symbol(T, Decl(typeCall.ts, 71, 13)) +>v : Symbol(v, Decl(typeCall.ts, 71, 16)) +>T : Symbol(T, Decl(typeCall.ts, 71, 13)) +>v : Symbol(v, Decl(typeCall.ts, 71, 16)) +>T : Symbol(T, Decl(typeCall.ts, 71, 13)) +>a : Symbol(a, Decl(typeCall.ts, 71, 38)) +>b : Symbol(b, Decl(typeCall.ts, 71, 44)) +>c : Symbol(c, Decl(typeCall.ts, 71, 50)) +>a : Symbol(a, Decl(typeCall.ts, 71, 62)) +>b : Symbol(b, Decl(typeCall.ts, 71, 68)) +>c : Symbol(c, Decl(typeCall.ts, 71, 74)) type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; ->Inc : Symbol(Inc, Decl(typeCall.ts, 68, 83)) ->k : Symbol(k, Decl(typeCall.ts, 70, 14)) +>Inc : Symbol(Inc, Decl(typeCall.ts, 71, 83)) +>k : Symbol(k, Decl(typeCall.ts, 73, 14)) type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; ->StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 70, 98)) ->k : Symbol(k, Decl(typeCall.ts, 71, 25)) +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 73, 98)) +>k : Symbol(k, Decl(typeCall.ts, 74, 25)) type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; ->TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 71, 82)) ->Arr : Symbol(Arr, Decl(typeCall.ts, 72, 19)) ->I : Symbol(I, Decl(typeCall.ts, 72, 37)) ->K : Symbol(K, Decl(typeCall.ts, 72, 61)) ->Arr : Symbol(Arr, Decl(typeCall.ts, 72, 19)) ->k : Symbol(k, Decl(typeCall.ts, 72, 89)) ->I : Symbol(I, Decl(typeCall.ts, 72, 37)) +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 74, 82)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 75, 19)) +>I : Symbol(I, Decl(typeCall.ts, 75, 37)) +>K : Symbol(K, Decl(typeCall.ts, 75, 61)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 75, 19)) +>k : Symbol(k, Decl(typeCall.ts, 75, 89)) +>I : Symbol(I, Decl(typeCall.ts, 75, 37)) type PathFn, I extends string = '0'> = ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) ->T : Symbol(T, Decl(typeCall.ts, 73, 12)) ->k : Symbol(k, Decl(typeCall.ts, 73, 25)) ->R : Symbol(R, Decl(typeCall.ts, 73, 43)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>T : Symbol(T, Decl(typeCall.ts, 76, 12)) +>k : Symbol(k, Decl(typeCall.ts, 76, 25)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->I : Symbol(I, Decl(typeCall.ts, 73, 68)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) { 1: PathFn, 0: T }[TupleHasIndex]; ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) ->T : Symbol(T, Decl(typeCall.ts, 73, 12)) ->R : Symbol(R, Decl(typeCall.ts, 73, 43)) ->StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 70, 98)) ->I : Symbol(I, Decl(typeCall.ts, 73, 68)) ->R : Symbol(R, Decl(typeCall.ts, 73, 43)) ->Inc : Symbol(Inc, Decl(typeCall.ts, 68, 83)) ->I : Symbol(I, Decl(typeCall.ts, 73, 68)) ->T : Symbol(T, Decl(typeCall.ts, 73, 12)) ->TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 71, 82)) ->R : Symbol(R, Decl(typeCall.ts, 73, 43)) ->I : Symbol(I, Decl(typeCall.ts, 73, 68)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>T : Symbol(T, Decl(typeCall.ts, 76, 12)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 73, 98)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) +>Inc : Symbol(Inc, Decl(typeCall.ts, 71, 83)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) +>T : Symbol(T, Decl(typeCall.ts, 76, 12)) +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 74, 82)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; ->PathTest : Symbol(PathTest, Decl(typeCall.ts, 74, 81)) ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) ->a : Symbol(a, Decl(typeCall.ts, 75, 24)) ->b : Symbol(b, Decl(typeCall.ts, 75, 29)) ->d : Symbol(d, Decl(typeCall.ts, 75, 40)) +>PathTest : Symbol(PathTest, Decl(typeCall.ts, 77, 81)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>a : Symbol(a, Decl(typeCall.ts, 78, 24)) +>b : Symbol(b, Decl(typeCall.ts, 78, 29)) +>d : Symbol(d, Decl(typeCall.ts, 78, 40)) declare function path>(obj: T, path: R): PathFn; ->path : Symbol(path, Decl(typeCall.ts, 75, 78)) ->T : Symbol(T, Decl(typeCall.ts, 76, 22)) ->k : Symbol(k, Decl(typeCall.ts, 76, 35)) ->R : Symbol(R, Decl(typeCall.ts, 76, 53)) +>path : Symbol(path, Decl(typeCall.ts, 78, 78)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>k : Symbol(k, Decl(typeCall.ts, 79, 35)) +>R : Symbol(R, Decl(typeCall.ts, 79, 53)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->obj : Symbol(obj, Decl(typeCall.ts, 76, 79)) ->T : Symbol(T, Decl(typeCall.ts, 76, 22)) ->path : Symbol(path, Decl(typeCall.ts, 76, 86)) ->R : Symbol(R, Decl(typeCall.ts, 76, 53)) ->PathFn : Symbol(PathFn, Decl(typeCall.ts, 72, 111)) ->T : Symbol(T, Decl(typeCall.ts, 76, 22)) ->R : Symbol(R, Decl(typeCall.ts, 76, 53)) +>obj : Symbol(obj, Decl(typeCall.ts, 79, 79)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>path : Symbol(path, Decl(typeCall.ts, 79, 86)) +>R : Symbol(R, Decl(typeCall.ts, 79, 53)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>R : Symbol(R, Decl(typeCall.ts, 79, 53)) const obj = null! as { a: { b: ['c', { d: 'e' }] } }; ->obj : Symbol(obj, Decl(typeCall.ts, 77, 5)) ->a : Symbol(a, Decl(typeCall.ts, 77, 22)) ->b : Symbol(b, Decl(typeCall.ts, 77, 27)) ->d : Symbol(d, Decl(typeCall.ts, 77, 38)) +>obj : Symbol(obj, Decl(typeCall.ts, 80, 5)) +>a : Symbol(a, Decl(typeCall.ts, 80, 22)) +>b : Symbol(b, Decl(typeCall.ts, 80, 27)) +>d : Symbol(d, Decl(typeCall.ts, 80, 38)) const keys = null! as ['a', 'b', '1', 'd']; ->keys : Symbol(keys, Decl(typeCall.ts, 78, 5)) +>keys : Symbol(keys, Decl(typeCall.ts, 81, 5)) const pathTest = path(obj, keys); ->pathTest : Symbol(pathTest, Decl(typeCall.ts, 79, 5)) ->path : Symbol(path, Decl(typeCall.ts, 75, 78)) ->obj : Symbol(obj, Decl(typeCall.ts, 77, 5)) ->keys : Symbol(keys, Decl(typeCall.ts, 78, 5)) +>pathTest : Symbol(pathTest, Decl(typeCall.ts, 82, 5)) +>path : Symbol(path, Decl(typeCall.ts, 78, 78)) +>obj : Symbol(obj, Decl(typeCall.ts, 80, 5)) +>keys : Symbol(keys, Decl(typeCall.ts, 81, 5)) // "e" @@ -357,539 +344,516 @@ const pathTest = path(obj, keys); // binary function composition type Fn1 = (v1: T1[]) => { [k: string]: T1 }; ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) ->T1 : Symbol(T1, Decl(typeCall.ts, 79, 12)) ->v1 : Symbol(v1, Decl(typeCall.ts, 79, 31)) ->T1 : Symbol(T1, Decl(typeCall.ts, 79, 12)) ->k : Symbol(k, Decl(typeCall.ts, 79, 47)) ->T1 : Symbol(T1, Decl(typeCall.ts, 79, 12)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) +>T1 : Symbol(T1, Decl(typeCall.ts, 104, 12)) +>v1 : Symbol(v1, Decl(typeCall.ts, 104, 31)) +>T1 : Symbol(T1, Decl(typeCall.ts, 104, 12)) +>k : Symbol(k, Decl(typeCall.ts, 104, 47)) +>T1 : Symbol(T1, Decl(typeCall.ts, 104, 12)) type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) ->T2 : Symbol(T2, Decl(typeCall.ts, 80, 12)) ->v2 : Symbol(v2, Decl(typeCall.ts, 80, 16)) ->k : Symbol(k, Decl(typeCall.ts, 80, 23)) ->T2 : Symbol(T2, Decl(typeCall.ts, 80, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>T2 : Symbol(T2, Decl(typeCall.ts, 105, 12)) +>v2 : Symbol(v2, Decl(typeCall.ts, 105, 16)) +>k : Symbol(k, Decl(typeCall.ts, 105, 23)) +>T2 : Symbol(T2, Decl(typeCall.ts, 105, 12)) >ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) ->T2 : Symbol(T2, Decl(typeCall.ts, 80, 12)) +>T2 : Symbol(T2, Decl(typeCall.ts, 105, 12)) let fn1 = null! as Fn1; ->fn1 : Symbol(fn1, Decl(typeCall.ts, 81, 3)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 106, 3)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) let fn2 = null! as Fn2; ->fn2 : Symbol(fn2, Decl(typeCall.ts, 82, 3)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 107, 3)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) type Fn3 = (v3: T3) => Fn2(Fn1(T3)); ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 82, 23)) ->T3 : Symbol(T3, Decl(typeCall.ts, 83, 12)) ->v3 : Symbol(v3, Decl(typeCall.ts, 83, 33)) ->T3 : Symbol(T3, Decl(typeCall.ts, 83, 12)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) ->T3 : Symbol(T3, Decl(typeCall.ts, 83, 12)) - -// type Fn4 = Fn3(1); // errors, ok +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) +>T3 : Symbol(T3, Decl(typeCall.ts, 108, 12)) +>v3 : Symbol(v3, Decl(typeCall.ts, 108, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 108, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 108, 12)) + let ones = null! as 1[]; ->ones : Symbol(ones, Decl(typeCall.ts, 85, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 109, 3)) type Fn4b = Fn3(typeof ones); ->Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 85, 24)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 82, 23)) ->ones : Symbol(ones, Decl(typeCall.ts, 85, 3)) +>Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 109, 24)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) +>ones : Symbol(ones, Decl(typeCall.ts, 109, 3)) // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); ->Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 86, 29)) ->Fn3 : Symbol(Fn3, Decl(typeCall.ts, 82, 23)) +>Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 110, 29)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. -// let x = fn2(fn1(1)); // errors with not assignable, ok -// type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); ->y : Symbol(y, Decl(typeCall.ts, 92, 3)) ->fn2 : Symbol(fn2, Decl(typeCall.ts, 82, 3)) ->fn1 : Symbol(fn1, Decl(typeCall.ts, 81, 3)) ->ones : Symbol(ones, Decl(typeCall.ts, 85, 3)) +>y : Symbol(y, Decl(typeCall.ts, 114, 3)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 107, 3)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 106, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 109, 3)) type Y = Fn2(Fn1(1[])); ->Y : Symbol(Y, Decl(typeCall.ts, 92, 23)) ->Fn2 : Symbol(Fn2, Decl(typeCall.ts, 79, 64)) ->Fn1 : Symbol(Fn1, Decl(typeCall.ts, 57, 33)) +>Y : Symbol(Y, Decl(typeCall.ts, 114, 23)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) interface isT { ->isT : Symbol(isT, Decl(typeCall.ts, 93, 23)) ->T : Symbol(T, Decl(typeCall.ts, 95, 14)) +>isT : Symbol(isT, Decl(typeCall.ts, 115, 23)) +>T : Symbol(T, Decl(typeCall.ts, 117, 14)) (v: never): '0'; ->v : Symbol(v, Decl(typeCall.ts, 96, 3)) +>v : Symbol(v, Decl(typeCall.ts, 118, 3)) (v: T): '1'; ->v : Symbol(v, Decl(typeCall.ts, 97, 3)) ->T : Symbol(T, Decl(typeCall.ts, 95, 14)) +>v : Symbol(v, Decl(typeCall.ts, 119, 3)) +>T : Symbol(T, Decl(typeCall.ts, 117, 14)) (v: any): '0'; ->v : Symbol(v, Decl(typeCall.ts, 98, 3)) +>v : Symbol(v, Decl(typeCall.ts, 120, 3)) } type Matches = isT(V); ->Matches : Symbol(Matches, Decl(typeCall.ts, 99, 1)) ->V : Symbol(V, Decl(typeCall.ts, 100, 13)) ->T : Symbol(T, Decl(typeCall.ts, 100, 15)) ->isT : Symbol(isT, Decl(typeCall.ts, 93, 23)) ->T : Symbol(T, Decl(typeCall.ts, 100, 15)) ->V : Symbol(V, Decl(typeCall.ts, 100, 13)) +>Matches : Symbol(Matches, Decl(typeCall.ts, 121, 1)) +>V : Symbol(V, Decl(typeCall.ts, 122, 13)) +>T : Symbol(T, Decl(typeCall.ts, 122, 15)) +>isT : Symbol(isT, Decl(typeCall.ts, 115, 23)) +>T : Symbol(T, Decl(typeCall.ts, 122, 15)) +>V : Symbol(V, Decl(typeCall.ts, 122, 13)) type isBool = isT; ->isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) ->isT : Symbol(isT, Decl(typeCall.ts, 93, 23)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) +>isT : Symbol(isT, Decl(typeCall.ts, 115, 23)) let falseBool: isBool(false); // 1 ->falseBool : Symbol(falseBool, Decl(typeCall.ts, 102, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) +>falseBool : Symbol(falseBool, Decl(typeCall.ts, 124, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) let trueBool: isBool(true); // 1 ->trueBool : Symbol(trueBool, Decl(typeCall.ts, 103, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) +>trueBool : Symbol(trueBool, Decl(typeCall.ts, 125, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) let strBool: isBool(string); // 0 ->strBool : Symbol(strBool, Decl(typeCall.ts, 104, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) +>strBool : Symbol(strBool, Decl(typeCall.ts, 53, 44), Decl(typeCall.ts, 126, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) let anyBool: isBool(any); // 0 ->anyBool : Symbol(anyBool, Decl(typeCall.ts, 105, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) +>anyBool : Symbol(anyBool, Decl(typeCall.ts, 127, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) let neverBool: isBool(never); // 0 ->neverBool : Symbol(neverBool, Decl(typeCall.ts, 106, 3)) ->isBool : Symbol(isBool, Decl(typeCall.ts, 100, 31)) +>neverBool : Symbol(neverBool, Decl(typeCall.ts, 128, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) type Assert = ((v: U | null | undefined) => U)(T); ->Assert : Symbol(Assert, Decl(typeCall.ts, 106, 29)) ->T : Symbol(T, Decl(typeCall.ts, 108, 12)) ->U : Symbol(U, Decl(typeCall.ts, 108, 19)) ->v : Symbol(v, Decl(typeCall.ts, 108, 22)) ->U : Symbol(U, Decl(typeCall.ts, 108, 19)) ->U : Symbol(U, Decl(typeCall.ts, 108, 19)) ->T : Symbol(T, Decl(typeCall.ts, 108, 12)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 128, 29)) +>T : Symbol(T, Decl(typeCall.ts, 130, 12)) +>U : Symbol(U, Decl(typeCall.ts, 130, 19)) +>v : Symbol(v, Decl(typeCall.ts, 130, 22)) +>U : Symbol(U, Decl(typeCall.ts, 130, 19)) +>U : Symbol(U, Decl(typeCall.ts, 130, 19)) +>T : Symbol(T, Decl(typeCall.ts, 130, 12)) let assert: Assert; // string ->assert : Symbol(assert, Decl(typeCall.ts, 109, 3)) ->Assert : Symbol(Assert, Decl(typeCall.ts, 106, 29)) +>assert : Symbol(assert, Decl(typeCall.ts, 131, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 128, 29)) type Minus = ((v: U | B) => U)(A); ->Minus : Symbol(Minus, Decl(typeCall.ts, 109, 39)) ->A : Symbol(A, Decl(typeCall.ts, 111, 11)) ->B : Symbol(B, Decl(typeCall.ts, 111, 13)) ->U : Symbol(U, Decl(typeCall.ts, 111, 21)) ->v : Symbol(v, Decl(typeCall.ts, 111, 24)) ->U : Symbol(U, Decl(typeCall.ts, 111, 21)) ->B : Symbol(B, Decl(typeCall.ts, 111, 13)) ->U : Symbol(U, Decl(typeCall.ts, 111, 21)) ->A : Symbol(A, Decl(typeCall.ts, 111, 11)) +>Minus : Symbol(Minus, Decl(typeCall.ts, 131, 39)) +>A : Symbol(A, Decl(typeCall.ts, 133, 11)) +>B : Symbol(B, Decl(typeCall.ts, 133, 13)) +>U : Symbol(U, Decl(typeCall.ts, 133, 21)) +>v : Symbol(v, Decl(typeCall.ts, 133, 24)) +>U : Symbol(U, Decl(typeCall.ts, 133, 21)) +>B : Symbol(B, Decl(typeCall.ts, 133, 13)) +>U : Symbol(U, Decl(typeCall.ts, 133, 21)) +>A : Symbol(A, Decl(typeCall.ts, 133, 11)) let noNumbers: Minus; // string ->noNumbers : Symbol(noNumbers, Decl(typeCall.ts, 112, 3)) ->Minus : Symbol(Minus, Decl(typeCall.ts, 109, 39)) +>noNumbers : Symbol(noNumbers, Decl(typeCall.ts, 134, 3)) +>Minus : Symbol(Minus, Decl(typeCall.ts, 131, 39)) interface UnwrapPromise { ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) (v: PromiseLike): UnwrapPromise(U); ->U : Symbol(U, Decl(typeCall.ts, 115, 3)) ->v : Symbol(v, Decl(typeCall.ts, 115, 6)) +>U : Symbol(U, Decl(typeCall.ts, 137, 3)) +>v : Symbol(v, Decl(typeCall.ts, 137, 6)) >PromiseLike : Symbol(PromiseLike, Decl(lib.d.ts, --, --)) ->U : Symbol(U, Decl(typeCall.ts, 115, 3)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) ->U : Symbol(U, Decl(typeCall.ts, 115, 3)) +>U : Symbol(U, Decl(typeCall.ts, 137, 3)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>U : Symbol(U, Decl(typeCall.ts, 137, 3)) (v: U): U; ->U : Symbol(U, Decl(typeCall.ts, 116, 3)) ->v : Symbol(v, Decl(typeCall.ts, 116, 6)) ->U : Symbol(U, Decl(typeCall.ts, 116, 3)) ->U : Symbol(U, Decl(typeCall.ts, 116, 3)) +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) +>v : Symbol(v, Decl(typeCall.ts, 138, 6)) +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) }; declare const testUnwrap1: UnwrapPromise(string); ->testUnwrap1 : Symbol(testUnwrap1, Decl(typeCall.ts, 118, 13)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) +>testUnwrap1 : Symbol(testUnwrap1, Decl(typeCall.ts, 140, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) declare const testUnwrap2: UnwrapPromise(Promise); ->testUnwrap2 : Symbol(testUnwrap2, Decl(typeCall.ts, 119, 13)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>testUnwrap2 : Symbol(testUnwrap2, Decl(typeCall.ts, 141, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) declare const testUnwrap3: UnwrapPromise(boolean | Promise); ->testUnwrap3 : Symbol(testUnwrap3, Decl(typeCall.ts, 120, 13)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>testUnwrap3 : Symbol(testUnwrap3, Decl(typeCall.ts, 142, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) declare function myThen( ->myThen : Symbol(myThen, Decl(typeCall.ts, 120, 68)) ->T : Symbol(T, Decl(typeCall.ts, 121, 24)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 121, 26)) ->T : Symbol(T, Decl(typeCall.ts, 121, 24)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 121, 40)) +>myThen : Symbol(myThen, Decl(typeCall.ts, 142, 68)) +>T : Symbol(T, Decl(typeCall.ts, 143, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 143, 26)) +>T : Symbol(T, Decl(typeCall.ts, 143, 24)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 143, 40)) prom: Promise, ->prom : Symbol(prom, Decl(typeCall.ts, 121, 59)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) ->T : Symbol(T, Decl(typeCall.ts, 121, 24)) +>prom : Symbol(prom, Decl(typeCall.ts, 143, 59)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>T : Symbol(T, Decl(typeCall.ts, 143, 24)) onfulfilled?: ((value: T) => TResult1) | undefined | null, ->onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 122, 25)) ->value : Symbol(value, Decl(typeCall.ts, 123, 24)) ->T : Symbol(T, Decl(typeCall.ts, 121, 24)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 121, 26)) +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 144, 25)) +>value : Symbol(value, Decl(typeCall.ts, 145, 24)) +>T : Symbol(T, Decl(typeCall.ts, 143, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 143, 26)) onrejected?: ((reason: any) => TResult2) | undefined | null ->onrejected : Symbol(onrejected, Decl(typeCall.ts, 123, 66)) ->reason : Symbol(reason, Decl(typeCall.ts, 124, 23)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 121, 40)) +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 145, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 146, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 143, 40)) ): Promise; ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 121, 26)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 121, 40)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 143, 26)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 143, 40)) declare const pr: Promise; ->pr : Symbol(pr, Decl(typeCall.ts, 126, 13)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>pr : Symbol(pr, Decl(typeCall.ts, 148, 13)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) declare function f(x: number): Promise; ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) ->x : Symbol(x, Decl(typeCall.ts, 127, 19)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) +>x : Symbol(x, Decl(typeCall.ts, 149, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) declare function g(x: number): number | Promise; ->g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 127, 47)) ->x : Symbol(x, Decl(typeCall.ts, 128, 19)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 149, 47)) +>x : Symbol(x, Decl(typeCall.ts, 150, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) const testThen = myThen(pr, f, g); ->testThen : Symbol(testThen, Decl(typeCall.ts, 129, 5)) ->myThen : Symbol(myThen, Decl(typeCall.ts, 120, 68)) ->pr : Symbol(pr, Decl(typeCall.ts, 126, 13)) ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) ->g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 127, 47)) +>testThen : Symbol(testThen, Decl(typeCall.ts, 151, 5)) +>myThen : Symbol(myThen, Decl(typeCall.ts, 142, 68)) +>pr : Symbol(pr, Decl(typeCall.ts, 148, 13)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 149, 47)) interface Promise { ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) ->T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 18)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 18)) then( ->then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 22)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 132, 9)) ->T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 18)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 132, 22)) +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 22)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 154, 9)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 18)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 154, 22)) onfulfilled?: ((value: T) => TResult1) | undefined | null, ->onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 132, 41)) ->value : Symbol(value, Decl(typeCall.ts, 133, 24)) ->T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 18)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 132, 9)) +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 154, 41)) +>value : Symbol(value, Decl(typeCall.ts, 155, 24)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 18)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 154, 9)) onrejected?: ((reason: any) => TResult2) | undefined | null ->onrejected : Symbol(onrejected, Decl(typeCall.ts, 133, 66)) ->reason : Symbol(reason, Decl(typeCall.ts, 134, 23)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 132, 22)) +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 155, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 156, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 154, 22)) ): Promise; ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 129, 34)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 132, 9)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 112, 46)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 132, 22)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 154, 9)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 154, 22)) } -// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter -// of type '(value: number) => string | PromiseLike'; +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; const tryProm = pr.then((x: number) => { ->tryProm : Symbol(tryProm, Decl(typeCall.ts, 139, 5)) ->pr.then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 22)) ->pr : Symbol(pr, Decl(typeCall.ts, 126, 13)) ->then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 131, 22)) ->x : Symbol(x, Decl(typeCall.ts, 139, 25)) +>tryProm : Symbol(tryProm, Decl(typeCall.ts, 160, 5)) +>pr.then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 22)) +>pr : Symbol(pr, Decl(typeCall.ts, 148, 13)) +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 22)) +>x : Symbol(x, Decl(typeCall.ts, 160, 25)) if (x < 0) return f(x); ->x : Symbol(x, Decl(typeCall.ts, 139, 25)) ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 126, 34)) ->x : Symbol(x, Decl(typeCall.ts, 139, 25)) +>x : Symbol(x, Decl(typeCall.ts, 160, 25)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) +>x : Symbol(x, Decl(typeCall.ts, 160, 25)) return x; ->x : Symbol(x, Decl(typeCall.ts, 139, 25)) +>x : Symbol(x, Decl(typeCall.ts, 160, 25)) }); interface ObjectHasStringIndex { ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 142, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 163, 3)) // (o: T): T[string]; (o: { [k: string]: any }): '1'; ->o : Symbol(o, Decl(typeCall.ts, 146, 3)) ->k : Symbol(k, Decl(typeCall.ts, 146, 9)) +>o : Symbol(o, Decl(typeCall.ts, 167, 3)) +>k : Symbol(k, Decl(typeCall.ts, 167, 9)) (o: {}): '0'; ->o : Symbol(o, Decl(typeCall.ts, 147, 3)) +>o : Symbol(o, Decl(typeCall.ts, 168, 3)) } let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' ->ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 149, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 142, 3)) ->k : Symbol(k, Decl(typeCall.ts, 149, 55)) +>ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 170, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 163, 3)) +>k : Symbol(k, Decl(typeCall.ts, 170, 55)) let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. ->ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 150, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 142, 3)) ->a : Symbol(a, Decl(typeCall.ts, 150, 53)) +>ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 171, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 163, 3)) +>a : Symbol(a, Decl(typeCall.ts, 171, 53)) type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 150, 64)) ->T : Symbol(T, Decl(typeCall.ts, 152, 15)) ->k : Symbol(k, Decl(typeCall.ts, 152, 34)) ->K : Symbol(K, Decl(typeCall.ts, 152, 52)) ->T : Symbol(T, Decl(typeCall.ts, 152, 15)) ->T : Symbol(T, Decl(typeCall.ts, 152, 15)) ->K : Symbol(K, Decl(typeCall.ts, 152, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 171, 64)) +>T : Symbol(T, Decl(typeCall.ts, 173, 15)) +>k : Symbol(k, Decl(typeCall.ts, 173, 34)) +>K : Symbol(K, Decl(typeCall.ts, 173, 52)) +>T : Symbol(T, Decl(typeCall.ts, 173, 15)) +>T : Symbol(T, Decl(typeCall.ts, 173, 15)) +>K : Symbol(K, Decl(typeCall.ts, 173, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 152, 85)) ->T : Symbol(T, Decl(typeCall.ts, 153, 16)) ->k : Symbol(k, Decl(typeCall.ts, 153, 29)) ->K : Symbol(K, Decl(typeCall.ts, 153, 53)) ->T : Symbol(T, Decl(typeCall.ts, 153, 16)) ->T : Symbol(T, Decl(typeCall.ts, 153, 16)) ->K : Symbol(K, Decl(typeCall.ts, 153, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 173, 85)) +>T : Symbol(T, Decl(typeCall.ts, 174, 16)) +>k : Symbol(k, Decl(typeCall.ts, 174, 29)) +>K : Symbol(K, Decl(typeCall.ts, 174, 53)) +>T : Symbol(T, Decl(typeCall.ts, 174, 16)) +>T : Symbol(T, Decl(typeCall.ts, 174, 16)) +>K : Symbol(K, Decl(typeCall.ts, 174, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 153, 82)) ->T : Symbol(T, Decl(typeCall.ts, 154, 22)) ->k : Symbol(k, Decl(typeCall.ts, 154, 35)) ->K : Symbol(K, Decl(typeCall.ts, 154, 65)) ->T : Symbol(T, Decl(typeCall.ts, 154, 22)) ->T : Symbol(T, Decl(typeCall.ts, 154, 22)) ->K : Symbol(K, Decl(typeCall.ts, 154, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 174, 82)) +>T : Symbol(T, Decl(typeCall.ts, 175, 22)) +>k : Symbol(k, Decl(typeCall.ts, 175, 35)) +>K : Symbol(K, Decl(typeCall.ts, 175, 65)) +>T : Symbol(T, Decl(typeCall.ts, 175, 22)) +>T : Symbol(T, Decl(typeCall.ts, 175, 22)) +>K : Symbol(K, Decl(typeCall.ts, 175, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 154, 89)) ->T : Symbol(T, Decl(typeCall.ts, 156, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 156, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 175, 89)) +>T : Symbol(T, Decl(typeCall.ts, 177, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 177, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 157, 5)) ->T : Symbol(T, Decl(typeCall.ts, 156, 12)) +>K : Symbol(K, Decl(typeCall.ts, 178, 5)) +>T : Symbol(T, Decl(typeCall.ts, 177, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 158, 5)) +>key : Symbol(key, Decl(typeCall.ts, 179, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 156, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 177, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 159, 7)) ->T : Symbol(T, Decl(typeCall.ts, 161, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 154, 89)) ->T : Symbol(T, Decl(typeCall.ts, 161, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 180, 7)) +>T : Symbol(T, Decl(typeCall.ts, 182, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 175, 89)) +>T : Symbol(T, Decl(typeCall.ts, 182, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 161, 59)) ->T : Symbol(T, Decl(typeCall.ts, 162, 15)) ->k : Symbol(k, Decl(typeCall.ts, 162, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 162, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 182, 59)) +>T : Symbol(T, Decl(typeCall.ts, 183, 15)) +>k : Symbol(k, Decl(typeCall.ts, 183, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 183, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 163, 5)) ->T : Symbol(T, Decl(typeCall.ts, 162, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 154, 89)) ->T : Symbol(T, Decl(typeCall.ts, 162, 15)) ->K : Symbol(K, Decl(typeCall.ts, 163, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 162, 52)) +>K : Symbol(K, Decl(typeCall.ts, 184, 5)) +>T : Symbol(T, Decl(typeCall.ts, 183, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 175, 89)) +>T : Symbol(T, Decl(typeCall.ts, 183, 15)) +>K : Symbol(K, Decl(typeCall.ts, 184, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 183, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 164, 2)) ->T : Symbol(T, Decl(typeCall.ts, 166, 15)) ->T : Symbol(T, Decl(typeCall.ts, 166, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 185, 2)) +>T : Symbol(T, Decl(typeCall.ts, 187, 15)) +>T : Symbol(T, Decl(typeCall.ts, 187, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 166, 50)) ->T : Symbol(T, Decl(typeCall.ts, 168, 12)) ->K : Symbol(K, Decl(typeCall.ts, 168, 38)) ->T : Symbol(T, Decl(typeCall.ts, 168, 12)) ->T : Symbol(T, Decl(typeCall.ts, 168, 12)) ->K : Symbol(K, Decl(typeCall.ts, 168, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 187, 50)) +>T : Symbol(T, Decl(typeCall.ts, 189, 12)) +>K : Symbol(K, Decl(typeCall.ts, 189, 38)) +>T : Symbol(T, Decl(typeCall.ts, 189, 12)) +>T : Symbol(T, Decl(typeCall.ts, 189, 12)) +>K : Symbol(K, Decl(typeCall.ts, 189, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 168, 66)) ->T : Symbol(T, Decl(typeCall.ts, 169, 12)) ->k : Symbol(k, Decl(typeCall.ts, 169, 31)) ->K : Symbol(K, Decl(typeCall.ts, 169, 61)) ->T : Symbol(T, Decl(typeCall.ts, 169, 12)) ->T : Symbol(T, Decl(typeCall.ts, 169, 12)) ->K : Symbol(K, Decl(typeCall.ts, 169, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 189, 66)) +>T : Symbol(T, Decl(typeCall.ts, 190, 12)) +>k : Symbol(k, Decl(typeCall.ts, 190, 31)) +>K : Symbol(K, Decl(typeCall.ts, 190, 61)) +>T : Symbol(T, Decl(typeCall.ts, 190, 12)) +>T : Symbol(T, Decl(typeCall.ts, 190, 12)) +>K : Symbol(K, Decl(typeCall.ts, 190, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 171, 12)) +>x : Symbol(x, Decl(typeCall.ts, 192, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 172, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 173, 14)) ->value : Symbol(value, Decl(typeCall.ts, 173, 28)) +>z : Symbol(z, Decl(typeCall.ts, 193, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 194, 14)) +>value : Symbol(value, Decl(typeCall.ts, 194, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 174, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 195, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 176, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 152, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 197, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 173, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 177, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 150, 64)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 198, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 171, 64)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 178, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 153, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 199, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 174, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 179, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 200, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 180, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 164, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 201, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 185, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 181, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 202, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 182, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 161, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 203, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 182, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 183, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 166, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 204, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 187, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 184, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 168, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 169, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 205, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 189, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 187, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 208, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 188, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 187, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 209, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 208, 3)) type Abc any> = T(); ->Abc : Symbol(Abc, Decl(typeCall.ts, 188, 20)) ->T : Symbol(T, Decl(typeCall.ts, 189, 9)) ->T : Symbol(T, Decl(typeCall.ts, 189, 9)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 209, 20)) +>T : Symbol(T, Decl(typeCall.ts, 210, 9)) +>T : Symbol(T, Decl(typeCall.ts, 210, 9)) let c1: Abc; ->c1 : Symbol(c1, Decl(typeCall.ts, 190, 3)) ->Abc : Symbol(Abc, Decl(typeCall.ts, 188, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 187, 3)) +>c1 : Symbol(c1, Decl(typeCall.ts, 211, 3)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 209, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 208, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 190, 23)) ->T : Symbol(T, Decl(typeCall.ts, 192, 24)) ->x : Symbol(x, Decl(typeCall.ts, 192, 45)) ->T : Symbol(T, Decl(typeCall.ts, 192, 24)) ->T : Symbol(T, Decl(typeCall.ts, 192, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 211, 23)) +>T : Symbol(T, Decl(typeCall.ts, 213, 24)) +>x : Symbol(x, Decl(typeCall.ts, 213, 45)) +>T : Symbol(T, Decl(typeCall.ts, 213, 24)) +>T : Symbol(T, Decl(typeCall.ts, 213, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 190, 23)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 211, 23)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 193, 30)) ->T : Symbol(T, Decl(typeCall.ts, 195, 24)) ->x : Symbol(x, Decl(typeCall.ts, 195, 45)) ->a : Symbol(a, Decl(typeCall.ts, 195, 49)) ->T : Symbol(T, Decl(typeCall.ts, 195, 24)) ->T : Symbol(T, Decl(typeCall.ts, 195, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 214, 30)) +>T : Symbol(T, Decl(typeCall.ts, 216, 24)) +>x : Symbol(x, Decl(typeCall.ts, 216, 45)) +>a : Symbol(a, Decl(typeCall.ts, 216, 49)) +>T : Symbol(T, Decl(typeCall.ts, 216, 24)) +>T : Symbol(T, Decl(typeCall.ts, 216, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 193, 30)) ->a : Symbol(a, Decl(typeCall.ts, 196, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 214, 30)) +>a : Symbol(a, Decl(typeCall.ts, 217, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 196, 37)) ->T : Symbol(T, Decl(typeCall.ts, 198, 24)) ->x : Symbol(x, Decl(typeCall.ts, 198, 27)) ->a : Symbol(a, Decl(typeCall.ts, 198, 31)) ->T : Symbol(T, Decl(typeCall.ts, 198, 24)) ->T : Symbol(T, Decl(typeCall.ts, 198, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 217, 37)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) +>x : Symbol(x, Decl(typeCall.ts, 219, 27)) +>a : Symbol(a, Decl(typeCall.ts, 219, 31)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 196, 37)) ->a : Symbol(a, Decl(typeCall.ts, 199, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 217, 37)) +>a : Symbol(a, Decl(typeCall.ts, 220, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 200, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 196, 37)) ->a : Symbol(a, Decl(typeCall.ts, 200, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 221, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 217, 37)) +>a : Symbol(a, Decl(typeCall.ts, 221, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 200, 58)) ->T : Symbol(T, Decl(typeCall.ts, 202, 24)) ->x : Symbol(x, Decl(typeCall.ts, 202, 27)) ->T : Symbol(T, Decl(typeCall.ts, 202, 24)) ->y : Symbol(y, Decl(typeCall.ts, 202, 32)) ->T : Symbol(T, Decl(typeCall.ts, 202, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 221, 58)) +>T : Symbol(T, Decl(typeCall.ts, 223, 24)) +>x : Symbol(x, Decl(typeCall.ts, 223, 27)) +>T : Symbol(T, Decl(typeCall.ts, 223, 24)) +>y : Symbol(y, Decl(typeCall.ts, 223, 32)) +>T : Symbol(T, Decl(typeCall.ts, 223, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 200, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 221, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 203, 19)) ->T : Symbol(T, Decl(typeCall.ts, 205, 23)) ->x : Symbol(x, Decl(typeCall.ts, 205, 26)) ->T : Symbol(T, Decl(typeCall.ts, 205, 23)) ->y : Symbol(y, Decl(typeCall.ts, 205, 31)) ->T : Symbol(T, Decl(typeCall.ts, 205, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 224, 19)) +>T : Symbol(T, Decl(typeCall.ts, 226, 23)) +>x : Symbol(x, Decl(typeCall.ts, 226, 26)) +>T : Symbol(T, Decl(typeCall.ts, 226, 23)) +>y : Symbol(y, Decl(typeCall.ts, 226, 31)) +>T : Symbol(T, Decl(typeCall.ts, 226, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 206, 9)) ->T : Symbol(T, Decl(typeCall.ts, 205, 23)) ->x : Symbol(x, Decl(typeCall.ts, 205, 26)) +>a : Symbol(a, Decl(typeCall.ts, 227, 9)) +>T : Symbol(T, Decl(typeCall.ts, 226, 23)) +>x : Symbol(x, Decl(typeCall.ts, 226, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 207, 9)) ->T : Symbol(T, Decl(typeCall.ts, 205, 23)) ->y : Symbol(y, Decl(typeCall.ts, 205, 31)) -} - -function comparability(x: T, y: () => T) { ->comparability : Symbol(comparability, Decl(typeCall.ts, 208, 1)) ->T : Symbol(T, Decl(typeCall.ts, 210, 23)) ->x : Symbol(x, Decl(typeCall.ts, 210, 26)) ->T : Symbol(T, Decl(typeCall.ts, 210, 23)) ->y : Symbol(y, Decl(typeCall.ts, 210, 31)) ->T : Symbol(T, Decl(typeCall.ts, 210, 23)) - - x === x; ->x : Symbol(x, Decl(typeCall.ts, 210, 26)) ->x : Symbol(x, Decl(typeCall.ts, 210, 26)) - - y === y; ->y : Symbol(y, Decl(typeCall.ts, 210, 31)) ->y : Symbol(y, Decl(typeCall.ts, 210, 31)) - - // x === y; // rightfully errors +>b : Symbol(b, Decl(typeCall.ts, 228, 9)) +>T : Symbol(T, Decl(typeCall.ts, 226, 23)) +>y : Symbol(y, Decl(typeCall.ts, 226, 31)) } // function mappedAssignability(x: T, y: CallMember) { diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 647fbef2703bf..85856864cf248 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -148,6 +148,11 @@ angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) interface BoolToString { >BoolToString : BoolToString + (v: false & true): never; +>v : false & true +>false : false +>true : true + (v: false): 'false'; >v : false >false : false @@ -155,6 +160,9 @@ interface BoolToString { (v: true): 'true'; >v : true >true : true + + (v: boolean): 'true' | 'false'; +>v : boolean } type strTrue = BoolToString(true); >strTrue : "true" @@ -167,54 +175,29 @@ type strFalse = BoolToString(false); >false : false type strEither = BoolToString(true | false); ->strEither : any +>strEither : "false" | "true" >BoolToString : BoolToString >true : true >false : false type strBool = BoolToString(boolean); ->strBool : any +>strBool : "false" | "true" >BoolToString : BoolToString -type strAny = BoolToString(any); ->strAny : any +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' +>strAny : "false" >BoolToString : BoolToString -declare function safeDivide< ->safeDivide : "whatever")({ (v: 0): "0"; (v: number): "1"; }(B))>(a: number, b: B) => number - - B extends number, ->B : B - - NotZero = ((v: '1') => 'whatever')({ ->NotZero : NotZero ->v : "1" - - (v: 0): '0'; ->v : 0 - - (v: number): '1'; ->v : number - - }(B)) ->B : B - ->(a: number, b: B): number; ->a : number ->b : B ->B : B - -safeDivide(3, 1); ->safeDivide(3, 1) : number ->safeDivide : "whatever")({ (v: 0): "0"; (v: number): "1"; }(B))>(a: number, b: B) => number ->3 : 3 ->1 : 1 - -safeDivide(3, 0); // fails, should error but doesn't ->safeDivide(3, 0) : number ->safeDivide : "whatever")({ (v: 0): "0"; (v: number): "1"; }(B))>(a: number, b: B) => number ->3 : 3 ->0 : 0 +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; >map : map @@ -263,8 +246,29 @@ declare function map any, O extends { [k: string]: T }, T>( >Fn : Fn >O : O -// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); +>z : { a: [{}]; b: [{}]; c: [{}]; } +>map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }) : { a: [{}]; b: [{}]; c: [{}]; } +>map : any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => map(Fn, O) +>(v: T) => [v] as [T] : (v: T) => [T] +>T : T +>v : T +>T : T +>[v] as [T] : [T] +>[v] : [T] +>v : T +>T : T +>{ a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 } : { a: 1; b: 2; c: 3; } +>{ a: 1, b: 2, c: 3 } : { a: 1; b: 2; c: 3; } +>a : number +>1 : 1 +>b : number +>2 : 2 +>c : number +>3 : 3 +>a : 1 +>b : 2 +>c : 3 type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; >Inc : Inc @@ -409,7 +413,6 @@ type Fn3 = (v3: T3) => Fn2(Fn1(T3)); >Fn1 : Fn1 >T3 : T3 -// type Fn4 = Fn3(1); // errors, ok let ones = null! as 1[]; >ones : 1[] >null! as 1[] : 1[] @@ -417,18 +420,16 @@ let ones = null! as 1[]; >null : null type Fn4b = Fn3(typeof ones); ->Fn4b : ReadonlyArray<{}> +>Fn4b : ReadonlyArray<1> >Fn3 : Fn3 >ones : 1[] // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); ->Fn4c : ReadonlyArray<{}> +>Fn4c : ReadonlyArray<1> >Fn3 : Fn3 // FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. -// let x = fn2(fn1(1)); // errors with not assignable, ok -// type X = Fn2(Fn1(1)); // errors with not assignable, ok let y = fn2(fn1(ones)); >y : ReadonlyArray<1> >fn2(fn1(ones)) : ReadonlyArray<1> @@ -635,8 +636,7 @@ interface Promise { >UnwrapPromise : UnwrapPromise >TResult2 : TResult2 } -// error: Argument of type '(x: number) => number | Promise' is not assignable to parameter -// of type '(value: number) => string | PromiseLike'; +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; const tryProm = pr.then((x: number) => { >tryProm : Promise> >pr.then((x: number) => { if (x < 0) return f(x); return x;}) : Promise> @@ -931,27 +931,6 @@ function assignability(x: T, y: () => T) { >y : () => T } -function comparability(x: T, y: () => T) { ->comparability : (x: T, y: () => T) => void ->T : T ->x : T ->T : T ->y : () => T ->T : T - - x === x; ->x === x : boolean ->x : T ->x : T - - y === y; ->y === y : boolean ->y : () => T ->y : () => T - - // x === y; // rightfully errors -} - // function mappedAssignability(x: T, y: CallMember) { // const d: T() = y; // } diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index a7f5a1f5b8a49..65a224dbefad5 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -48,30 +48,32 @@ declare function angularFactory R, R extends (f angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) interface BoolToString { + (v: false & true): never; (v: false): 'false'; (v: true): 'true'; + (v: boolean): 'true' | 'false'; } type strTrue = BoolToString(true); type strFalse = BoolToString(false); type strEither = BoolToString(true | false); type strBool = BoolToString(boolean); -type strAny = BoolToString(any); - -declare function safeDivide< - B extends number, - NotZero = ((v: '1') => 'whatever')({ - (v: 0): '0'; - (v: number): '1'; - }(B)) ->(a: number, b: B): number; -safeDivide(3, 1); -safeDivide(3, 0); // fails, should error but doesn't +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' + +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); -// let z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -// // fails with error: Cannot read property 'parent' of undefined at createDiagnosticForNodeFromMessageChain +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; From d602415d0c1183a44d16221387417845961b666f Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Mon, 11 Sep 2017 23:39:37 +0800 Subject: [PATCH 24/25] union-proof type calls, fixes `awaited` use-case from #17077 --- src/compiler/checker.ts | 49 +- tests/baselines/reference/typeCall.js | 17 +- tests/baselines/reference/typeCall.symbols | 560 +++++++++++---------- tests/baselines/reference/typeCall.types | 70 ++- tests/cases/compiler/typeCall.ts | 16 +- 5 files changed, 417 insertions(+), 295 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6ee4b12110133..58482dbabce12 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7587,9 +7587,52 @@ namespace ts { function getTypeFromTypeCall(type: TypeCallType, node: TypeCallTypeNode): Type { const fn = type.function; const args = type.arguments; - const calls = getSignaturesOfType(fn, SignatureKind.Call); - const sig = resolveCall(node, calls, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, args); - return sig ? getReturnTypeOfSignature(sig) : unknownType; + const candidates = getSignaturesOfType(fn, SignatureKind.Call); + const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; + if (isSingleNonGenericCandidate) { + const sig = resolveCall(node, candidates, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, args); + return sig ? getReturnTypeOfSignature(sig) : unknownType; + } + else { + // we have unions and they matter -- separately calculate the result for each permutation + const types: Type[] = []; + const indices: number[] = map(args, (tp: Type, i: number) => tp.flags & TypeFlags.Union && + some(candidates, (sig: Signature) => isGenericObjectType(getTypeAtPosition(sig, i))) ? + // ^ future consideration: argument/parameter i correspondence breaks down with tuple spreads + 0 : undefined); + const argTypes: Array = map(args, (tp: Type, i: number) => indices[i] !== undefined ? (tp).types : tp); + checkParams: while (true) { + const myArgs = map(argTypes, (tp: Type[] | Type, i: number) => { + const argIdx = indices[i]; + return argIdx === undefined ? tp : (tp)[argIdx]; + }); + const sig = resolveCall(node, candidates, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, myArgs); + if (sig) { + types.push(getReturnTypeOfSignature(sig)); + } + // increment the next index to try the next permutation + for (let i = 0; i < indices.length; i++) { + const idx = indices[i]; + if (idx === undefined) { + // nothing to do here, try switching the next argument + continue; + } + else if (idx < (argTypes[i]).length - 1) { + // can increment without overflow + indices[i] = indices[i] + 1; + continue checkParams; + } + else { + // overflow, try switching the next argument as well + indices[i] = 0; + continue; + } + } + // all options tried, full overflow throughout for-loop, done + break; + } + return getUnionType(types); + } } function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index a7eaa7e839c88..4acfefcfa89ca 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -90,7 +90,7 @@ const pathTest = path(obj, keys); // R extends any[], // I extends string = '0' // > = { 1: Reduce, 0: T }[TupleHasIndex]; -// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// // fails with error: Cannot read property 'flags' of undefined // declare function reduce< // Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, // R extends any[], @@ -108,13 +108,13 @@ type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; let fn1 = null! as Fn1; let fn2 = null! as Fn2; type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); let ones = null! as 1[]; type Fn4b = Fn3(typeof ones); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. let y = fn2(fn1(ones)); type Y = Fn2(Fn1(1[])); +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined interface isT { (v: never): '0'; @@ -129,10 +129,16 @@ let strBool: isBool(string); // 0 let anyBool: isBool(any); // 0 let neverBool: isBool(never); // 0 -type Assert = ((v: U | null | undefined) => U)(T); +type Assert = { + (v: null | undefined): never; + (v: U): U; +}(T); let assert: Assert; // string -type Minus = ((v: U | B) => U)(A); +type Minus = { + (v: B): never; + (v: U): U; +}(A); let noNumbers: Minus; // string interface UnwrapPromise { @@ -270,7 +276,6 @@ var pathTest = path(obj, keys); var fn1 = null; var fn2 = null; var ones = null; -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. var y = fn2(fn1(ones)); var falseBool; // 1 var trueBool; // 1 diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 01db619a96aa5..56ab0f23924ff 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -44,12 +44,12 @@ let a = 'foo'; >a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) type f = typeof f4(typeof a); ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) >f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) >a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) type g = (() => 1)(); ->g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 149, 47)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 155, 47)) type Id = (v: T) => T; >Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) @@ -330,7 +330,7 @@ const pathTest = path(obj, keys); // R extends any[], // I extends string = '0' // > = { 1: Reduce, 0: T }[TupleHasIndex]; -// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// // fails with error: Cannot read property 'flags' of undefined // declare function reduce< // Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, // R extends any[], @@ -377,33 +377,53 @@ type Fn3 = (v3: T3) => Fn2(Fn1(T3)); >Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) >T3 : Symbol(T3, Decl(typeCall.ts, 108, 12)) +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); +>fn3 : Symbol(fn3, Decl(typeCall.ts, 108, 57)) +>Fun1 : Symbol(Fun1, Decl(typeCall.ts, 109, 21)) +>p1 : Symbol(p1, Decl(typeCall.ts, 109, 35)) +>P1 : Symbol(P1, Decl(typeCall.ts, 109, 95)) +>T : Symbol(T, Decl(typeCall.ts, 109, 99)) +>Fun2 : Symbol(Fun2, Decl(typeCall.ts, 109, 67)) +>v : Symbol(v, Decl(typeCall.ts, 109, 82)) +>T : Symbol(T, Decl(typeCall.ts, 109, 99)) +>P1 : Symbol(P1, Decl(typeCall.ts, 109, 95)) +>T : Symbol(T, Decl(typeCall.ts, 109, 99)) +>fun1 : Symbol(fun1, Decl(typeCall.ts, 109, 103)) +>Fun1 : Symbol(Fun1, Decl(typeCall.ts, 109, 21)) +>fun2 : Symbol(fun2, Decl(typeCall.ts, 109, 114)) +>Fun2 : Symbol(Fun2, Decl(typeCall.ts, 109, 67)) +>args : Symbol(args, Decl(typeCall.ts, 109, 129)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) +>P1 : Symbol(P1, Decl(typeCall.ts, 109, 95)) + let ones = null! as 1[]; ->ones : Symbol(ones, Decl(typeCall.ts, 109, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 110, 3)) type Fn4b = Fn3(typeof ones); ->Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 109, 24)) +>Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 110, 24)) >Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) ->ones : Symbol(ones, Decl(typeCall.ts, 109, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 110, 3)) -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); ->Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 110, 29)) +>Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 111, 29)) >Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. let y = fn2(fn1(ones)); ->y : Symbol(y, Decl(typeCall.ts, 114, 3)) +>y : Symbol(y, Decl(typeCall.ts, 113, 3)) >fn2 : Symbol(fn2, Decl(typeCall.ts, 107, 3)) >fn1 : Symbol(fn1, Decl(typeCall.ts, 106, 3)) ->ones : Symbol(ones, Decl(typeCall.ts, 109, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 110, 3)) type Y = Fn2(Fn1(1[])); ->Y : Symbol(Y, Decl(typeCall.ts, 114, 23)) +>Y : Symbol(Y, Decl(typeCall.ts, 113, 23)) >Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) >Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined + interface isT { ->isT : Symbol(isT, Decl(typeCall.ts, 115, 23)) +>isT : Symbol(isT, Decl(typeCall.ts, 114, 23)) >T : Symbol(T, Decl(typeCall.ts, 117, 14)) (v: never): '0'; @@ -420,13 +440,13 @@ type Matches = isT(V); >Matches : Symbol(Matches, Decl(typeCall.ts, 121, 1)) >V : Symbol(V, Decl(typeCall.ts, 122, 13)) >T : Symbol(T, Decl(typeCall.ts, 122, 15)) ->isT : Symbol(isT, Decl(typeCall.ts, 115, 23)) +>isT : Symbol(isT, Decl(typeCall.ts, 114, 23)) >T : Symbol(T, Decl(typeCall.ts, 122, 15)) >V : Symbol(V, Decl(typeCall.ts, 122, 13)) type isBool = isT; >isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) ->isT : Symbol(isT, Decl(typeCall.ts, 115, 23)) +>isT : Symbol(isT, Decl(typeCall.ts, 114, 23)) let falseBool: isBool(false); // 1 >falseBool : Symbol(falseBool, Decl(typeCall.ts, 124, 3)) @@ -448,412 +468,426 @@ let neverBool: isBool(never); // 0 >neverBool : Symbol(neverBool, Decl(typeCall.ts, 128, 3)) >isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) -type Assert = ((v: U | null | undefined) => U)(T); +type Assert = { >Assert : Symbol(Assert, Decl(typeCall.ts, 128, 29)) >T : Symbol(T, Decl(typeCall.ts, 130, 12)) ->U : Symbol(U, Decl(typeCall.ts, 130, 19)) ->v : Symbol(v, Decl(typeCall.ts, 130, 22)) ->U : Symbol(U, Decl(typeCall.ts, 130, 19)) ->U : Symbol(U, Decl(typeCall.ts, 130, 19)) + + (v: null | undefined): never; +>v : Symbol(v, Decl(typeCall.ts, 131, 3)) + + (v: U): U; +>U : Symbol(U, Decl(typeCall.ts, 132, 3)) +>v : Symbol(v, Decl(typeCall.ts, 132, 6)) +>U : Symbol(U, Decl(typeCall.ts, 132, 3)) +>U : Symbol(U, Decl(typeCall.ts, 132, 3)) + +}(T); >T : Symbol(T, Decl(typeCall.ts, 130, 12)) let assert: Assert; // string ->assert : Symbol(assert, Decl(typeCall.ts, 131, 3)) +>assert : Symbol(assert, Decl(typeCall.ts, 134, 3)) >Assert : Symbol(Assert, Decl(typeCall.ts, 128, 29)) -type Minus = ((v: U | B) => U)(A); ->Minus : Symbol(Minus, Decl(typeCall.ts, 131, 39)) ->A : Symbol(A, Decl(typeCall.ts, 133, 11)) ->B : Symbol(B, Decl(typeCall.ts, 133, 13)) ->U : Symbol(U, Decl(typeCall.ts, 133, 21)) ->v : Symbol(v, Decl(typeCall.ts, 133, 24)) ->U : Symbol(U, Decl(typeCall.ts, 133, 21)) ->B : Symbol(B, Decl(typeCall.ts, 133, 13)) ->U : Symbol(U, Decl(typeCall.ts, 133, 21)) ->A : Symbol(A, Decl(typeCall.ts, 133, 11)) +type Minus = { +>Minus : Symbol(Minus, Decl(typeCall.ts, 134, 39)) +>A : Symbol(A, Decl(typeCall.ts, 136, 11)) +>B : Symbol(B, Decl(typeCall.ts, 136, 13)) + + (v: B): never; +>v : Symbol(v, Decl(typeCall.ts, 137, 3)) +>B : Symbol(B, Decl(typeCall.ts, 136, 13)) + + (v: U): U; +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) +>v : Symbol(v, Decl(typeCall.ts, 138, 6)) +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) + +}(A); +>A : Symbol(A, Decl(typeCall.ts, 136, 11)) let noNumbers: Minus; // string ->noNumbers : Symbol(noNumbers, Decl(typeCall.ts, 134, 3)) ->Minus : Symbol(Minus, Decl(typeCall.ts, 131, 39)) +>noNumbers : Symbol(noNumbers, Decl(typeCall.ts, 140, 3)) +>Minus : Symbol(Minus, Decl(typeCall.ts, 134, 39)) interface UnwrapPromise { ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) (v: PromiseLike): UnwrapPromise(U); ->U : Symbol(U, Decl(typeCall.ts, 137, 3)) ->v : Symbol(v, Decl(typeCall.ts, 137, 6)) +>U : Symbol(U, Decl(typeCall.ts, 143, 3)) +>v : Symbol(v, Decl(typeCall.ts, 143, 6)) >PromiseLike : Symbol(PromiseLike, Decl(lib.d.ts, --, --)) ->U : Symbol(U, Decl(typeCall.ts, 137, 3)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) ->U : Symbol(U, Decl(typeCall.ts, 137, 3)) +>U : Symbol(U, Decl(typeCall.ts, 143, 3)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>U : Symbol(U, Decl(typeCall.ts, 143, 3)) (v: U): U; ->U : Symbol(U, Decl(typeCall.ts, 138, 3)) ->v : Symbol(v, Decl(typeCall.ts, 138, 6)) ->U : Symbol(U, Decl(typeCall.ts, 138, 3)) ->U : Symbol(U, Decl(typeCall.ts, 138, 3)) +>U : Symbol(U, Decl(typeCall.ts, 144, 3)) +>v : Symbol(v, Decl(typeCall.ts, 144, 6)) +>U : Symbol(U, Decl(typeCall.ts, 144, 3)) +>U : Symbol(U, Decl(typeCall.ts, 144, 3)) }; declare const testUnwrap1: UnwrapPromise(string); ->testUnwrap1 : Symbol(testUnwrap1, Decl(typeCall.ts, 140, 13)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) +>testUnwrap1 : Symbol(testUnwrap1, Decl(typeCall.ts, 146, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) declare const testUnwrap2: UnwrapPromise(Promise); ->testUnwrap2 : Symbol(testUnwrap2, Decl(typeCall.ts, 141, 13)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>testUnwrap2 : Symbol(testUnwrap2, Decl(typeCall.ts, 147, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) declare const testUnwrap3: UnwrapPromise(boolean | Promise); ->testUnwrap3 : Symbol(testUnwrap3, Decl(typeCall.ts, 142, 13)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>testUnwrap3 : Symbol(testUnwrap3, Decl(typeCall.ts, 148, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) declare function myThen( ->myThen : Symbol(myThen, Decl(typeCall.ts, 142, 68)) ->T : Symbol(T, Decl(typeCall.ts, 143, 24)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 143, 26)) ->T : Symbol(T, Decl(typeCall.ts, 143, 24)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 143, 40)) +>myThen : Symbol(myThen, Decl(typeCall.ts, 148, 68)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 149, 26)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 149, 40)) prom: Promise, ->prom : Symbol(prom, Decl(typeCall.ts, 143, 59)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) ->T : Symbol(T, Decl(typeCall.ts, 143, 24)) +>prom : Symbol(prom, Decl(typeCall.ts, 149, 59)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) onfulfilled?: ((value: T) => TResult1) | undefined | null, ->onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 144, 25)) ->value : Symbol(value, Decl(typeCall.ts, 145, 24)) ->T : Symbol(T, Decl(typeCall.ts, 143, 24)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 143, 26)) +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 150, 25)) +>value : Symbol(value, Decl(typeCall.ts, 151, 24)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 149, 26)) onrejected?: ((reason: any) => TResult2) | undefined | null ->onrejected : Symbol(onrejected, Decl(typeCall.ts, 145, 66)) ->reason : Symbol(reason, Decl(typeCall.ts, 146, 23)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 143, 40)) +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 151, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 152, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 149, 40)) ): Promise; ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 143, 26)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 143, 40)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 149, 26)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 149, 40)) declare const pr: Promise; ->pr : Symbol(pr, Decl(typeCall.ts, 148, 13)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>pr : Symbol(pr, Decl(typeCall.ts, 154, 13)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) declare function f(x: number): Promise; ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) ->x : Symbol(x, Decl(typeCall.ts, 149, 19)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) +>x : Symbol(x, Decl(typeCall.ts, 155, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) declare function g(x: number): number | Promise; ->g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 149, 47)) ->x : Symbol(x, Decl(typeCall.ts, 150, 19)) ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 155, 47)) +>x : Symbol(x, Decl(typeCall.ts, 156, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) const testThen = myThen(pr, f, g); ->testThen : Symbol(testThen, Decl(typeCall.ts, 151, 5)) ->myThen : Symbol(myThen, Decl(typeCall.ts, 142, 68)) ->pr : Symbol(pr, Decl(typeCall.ts, 148, 13)) ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) ->g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 149, 47)) +>testThen : Symbol(testThen, Decl(typeCall.ts, 157, 5)) +>myThen : Symbol(myThen, Decl(typeCall.ts, 148, 68)) +>pr : Symbol(pr, Decl(typeCall.ts, 154, 13)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 155, 47)) interface Promise { ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) ->T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 18)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 18)) then( ->then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 22)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 154, 9)) ->T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 18)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 154, 22)) +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 22)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 160, 9)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 18)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 160, 22)) onfulfilled?: ((value: T) => TResult1) | undefined | null, ->onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 154, 41)) ->value : Symbol(value, Decl(typeCall.ts, 155, 24)) ->T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 18)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 154, 9)) +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 160, 41)) +>value : Symbol(value, Decl(typeCall.ts, 161, 24)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 18)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 160, 9)) onrejected?: ((reason: any) => TResult2) | undefined | null ->onrejected : Symbol(onrejected, Decl(typeCall.ts, 155, 66)) ->reason : Symbol(reason, Decl(typeCall.ts, 156, 23)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 154, 22)) +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 161, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 162, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 160, 22)) ): Promise; ->Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 151, 34)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) ->TResult1 : Symbol(TResult1, Decl(typeCall.ts, 154, 9)) ->UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 134, 46)) ->TResult2 : Symbol(TResult2, Decl(typeCall.ts, 154, 22)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 160, 9)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 160, 22)) } // prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; const tryProm = pr.then((x: number) => { ->tryProm : Symbol(tryProm, Decl(typeCall.ts, 160, 5)) ->pr.then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 22)) ->pr : Symbol(pr, Decl(typeCall.ts, 148, 13)) ->then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 153, 22)) ->x : Symbol(x, Decl(typeCall.ts, 160, 25)) +>tryProm : Symbol(tryProm, Decl(typeCall.ts, 166, 5)) +>pr.then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 22)) +>pr : Symbol(pr, Decl(typeCall.ts, 154, 13)) +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 22)) +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) if (x < 0) return f(x); ->x : Symbol(x, Decl(typeCall.ts, 160, 25)) ->f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 148, 34)) ->x : Symbol(x, Decl(typeCall.ts, 160, 25)) +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) return x; ->x : Symbol(x, Decl(typeCall.ts, 160, 25)) +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) }); interface ObjectHasStringIndex { ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 163, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 169, 3)) // (o: T): T[string]; (o: { [k: string]: any }): '1'; ->o : Symbol(o, Decl(typeCall.ts, 167, 3)) ->k : Symbol(k, Decl(typeCall.ts, 167, 9)) +>o : Symbol(o, Decl(typeCall.ts, 173, 3)) +>k : Symbol(k, Decl(typeCall.ts, 173, 9)) (o: {}): '0'; ->o : Symbol(o, Decl(typeCall.ts, 168, 3)) +>o : Symbol(o, Decl(typeCall.ts, 174, 3)) } let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' ->ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 170, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 163, 3)) ->k : Symbol(k, Decl(typeCall.ts, 170, 55)) +>ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 176, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 169, 3)) +>k : Symbol(k, Decl(typeCall.ts, 176, 55)) let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. ->ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 171, 3)) ->ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 163, 3)) ->a : Symbol(a, Decl(typeCall.ts, 171, 53)) +>ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 177, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 169, 3)) +>a : Symbol(a, Decl(typeCall.ts, 177, 53)) type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 171, 64)) ->T : Symbol(T, Decl(typeCall.ts, 173, 15)) ->k : Symbol(k, Decl(typeCall.ts, 173, 34)) ->K : Symbol(K, Decl(typeCall.ts, 173, 52)) ->T : Symbol(T, Decl(typeCall.ts, 173, 15)) ->T : Symbol(T, Decl(typeCall.ts, 173, 15)) ->K : Symbol(K, Decl(typeCall.ts, 173, 52)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 177, 64)) +>T : Symbol(T, Decl(typeCall.ts, 179, 15)) +>k : Symbol(k, Decl(typeCall.ts, 179, 34)) +>K : Symbol(K, Decl(typeCall.ts, 179, 52)) +>T : Symbol(T, Decl(typeCall.ts, 179, 15)) +>T : Symbol(T, Decl(typeCall.ts, 179, 15)) +>K : Symbol(K, Decl(typeCall.ts, 179, 52)) type CallMember any }, K extends keyof T> = T[K](); ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 173, 85)) ->T : Symbol(T, Decl(typeCall.ts, 174, 16)) ->k : Symbol(k, Decl(typeCall.ts, 174, 29)) ->K : Symbol(K, Decl(typeCall.ts, 174, 53)) ->T : Symbol(T, Decl(typeCall.ts, 174, 16)) ->T : Symbol(T, Decl(typeCall.ts, 174, 16)) ->K : Symbol(K, Decl(typeCall.ts, 174, 53)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 179, 85)) +>T : Symbol(T, Decl(typeCall.ts, 180, 16)) +>k : Symbol(k, Decl(typeCall.ts, 180, 29)) +>K : Symbol(K, Decl(typeCall.ts, 180, 53)) +>T : Symbol(T, Decl(typeCall.ts, 180, 16)) +>T : Symbol(T, Decl(typeCall.ts, 180, 16)) +>K : Symbol(K, Decl(typeCall.ts, 180, 53)) type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 174, 82)) ->T : Symbol(T, Decl(typeCall.ts, 175, 22)) ->k : Symbol(k, Decl(typeCall.ts, 175, 35)) ->K : Symbol(K, Decl(typeCall.ts, 175, 65)) ->T : Symbol(T, Decl(typeCall.ts, 175, 22)) ->T : Symbol(T, Decl(typeCall.ts, 175, 22)) ->K : Symbol(K, Decl(typeCall.ts, 175, 65)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 180, 82)) +>T : Symbol(T, Decl(typeCall.ts, 181, 22)) +>k : Symbol(k, Decl(typeCall.ts, 181, 35)) +>K : Symbol(K, Decl(typeCall.ts, 181, 65)) +>T : Symbol(T, Decl(typeCall.ts, 181, 22)) +>T : Symbol(T, Decl(typeCall.ts, 181, 22)) +>K : Symbol(K, Decl(typeCall.ts, 181, 65)) type HasKey = ( ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 175, 89)) ->T : Symbol(T, Decl(typeCall.ts, 177, 12)) ->Key : Symbol(Key, Decl(typeCall.ts, 177, 14)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 181, 89)) +>T : Symbol(T, Decl(typeCall.ts, 183, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 183, 14)) { [K in keyof T]: 'true' } & ->K : Symbol(K, Decl(typeCall.ts, 178, 5)) ->T : Symbol(T, Decl(typeCall.ts, 177, 12)) +>K : Symbol(K, Decl(typeCall.ts, 184, 5)) +>T : Symbol(T, Decl(typeCall.ts, 183, 12)) { [key: string]: 'false' } ->key : Symbol(key, Decl(typeCall.ts, 179, 5)) +>key : Symbol(key, Decl(typeCall.ts, 185, 5)) )[Key]; ->Key : Symbol(Key, Decl(typeCall.ts, 177, 14)) +>Key : Symbol(Key, Decl(typeCall.ts, 183, 14)) type HasKindKey any> = HasKey; ->HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 180, 7)) ->T : Symbol(T, Decl(typeCall.ts, 182, 16)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 175, 89)) ->T : Symbol(T, Decl(typeCall.ts, 182, 16)) +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 186, 7)) +>T : Symbol(T, Decl(typeCall.ts, 188, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 181, 89)) +>T : Symbol(T, Decl(typeCall.ts, 188, 16)) type MapHasKey any }, Key extends string> = { ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 182, 59)) ->T : Symbol(T, Decl(typeCall.ts, 183, 15)) ->k : Symbol(k, Decl(typeCall.ts, 183, 28)) ->Key : Symbol(Key, Decl(typeCall.ts, 183, 52)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 188, 59)) +>T : Symbol(T, Decl(typeCall.ts, 189, 15)) +>k : Symbol(k, Decl(typeCall.ts, 189, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 189, 52)) [K in keyof T]: HasKey ->K : Symbol(K, Decl(typeCall.ts, 184, 5)) ->T : Symbol(T, Decl(typeCall.ts, 183, 15)) ->HasKey : Symbol(HasKey, Decl(typeCall.ts, 175, 89)) ->T : Symbol(T, Decl(typeCall.ts, 183, 15)) ->K : Symbol(K, Decl(typeCall.ts, 184, 5)) ->Key : Symbol(Key, Decl(typeCall.ts, 183, 52)) +>K : Symbol(K, Decl(typeCall.ts, 190, 5)) +>T : Symbol(T, Decl(typeCall.ts, 189, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 181, 89)) +>T : Symbol(T, Decl(typeCall.ts, 189, 15)) +>K : Symbol(K, Decl(typeCall.ts, 190, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 189, 52)) }; type KeyOfCall any> = keyof (T()); ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 185, 2)) ->T : Symbol(T, Decl(typeCall.ts, 187, 15)) ->T : Symbol(T, Decl(typeCall.ts, 187, 15)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 191, 2)) +>T : Symbol(T, Decl(typeCall.ts, 193, 15)) +>T : Symbol(T, Decl(typeCall.ts, 193, 15)) type Strip1 any> = { [K in keyof (T())]: T()[K] }; ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 187, 50)) ->T : Symbol(T, Decl(typeCall.ts, 189, 12)) ->K : Symbol(K, Decl(typeCall.ts, 189, 38)) ->T : Symbol(T, Decl(typeCall.ts, 189, 12)) ->T : Symbol(T, Decl(typeCall.ts, 189, 12)) ->K : Symbol(K, Decl(typeCall.ts, 189, 38)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 193, 50)) +>T : Symbol(T, Decl(typeCall.ts, 195, 12)) +>K : Symbol(K, Decl(typeCall.ts, 195, 38)) +>T : Symbol(T, Decl(typeCall.ts, 195, 12)) +>T : Symbol(T, Decl(typeCall.ts, 195, 12)) +>K : Symbol(K, Decl(typeCall.ts, 195, 38)) type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 189, 66)) ->T : Symbol(T, Decl(typeCall.ts, 190, 12)) ->k : Symbol(k, Decl(typeCall.ts, 190, 31)) ->K : Symbol(K, Decl(typeCall.ts, 190, 61)) ->T : Symbol(T, Decl(typeCall.ts, 190, 12)) ->T : Symbol(T, Decl(typeCall.ts, 190, 12)) ->K : Symbol(K, Decl(typeCall.ts, 190, 61)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 195, 66)) +>T : Symbol(T, Decl(typeCall.ts, 196, 12)) +>k : Symbol(k, Decl(typeCall.ts, 196, 31)) +>K : Symbol(K, Decl(typeCall.ts, 196, 61)) +>T : Symbol(T, Decl(typeCall.ts, 196, 12)) +>T : Symbol(T, Decl(typeCall.ts, 196, 12)) +>K : Symbol(K, Decl(typeCall.ts, 196, 61)) type Obj = { ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) x: () => number, ->x : Symbol(x, Decl(typeCall.ts, 192, 12)) +>x : Symbol(x, Decl(typeCall.ts, 198, 12)) z: () => { kind: 'Just', value: string } ->z : Symbol(z, Decl(typeCall.ts, 193, 20)) ->kind : Symbol(kind, Decl(typeCall.ts, 194, 14)) ->value : Symbol(value, Decl(typeCall.ts, 194, 28)) +>z : Symbol(z, Decl(typeCall.ts, 199, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 200, 14)) +>value : Symbol(value, Decl(typeCall.ts, 200, 28)) } type T1 = (() => number)(); ->T1 : Symbol(T1, Decl(typeCall.ts, 195, 1)) +>T1 : Symbol(T1, Decl(typeCall.ts, 201, 1)) type T7 = CallMember; ->T7 : Symbol(T7, Decl(typeCall.ts, 197, 27)) ->CallMember : Symbol(CallMember, Decl(typeCall.ts, 173, 85)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T7 : Symbol(T7, Decl(typeCall.ts, 203, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 179, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T8 = IndexCall<() => Obj, 'x'>; ->T8 : Symbol(T8, Decl(typeCall.ts, 198, 31)) ->IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 171, 64)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T8 : Symbol(T8, Decl(typeCall.ts, 204, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 177, 64)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T9 : Symbol(T9, Decl(typeCall.ts, 199, 36)) ->MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 174, 82)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T9 : Symbol(T9, Decl(typeCall.ts, 205, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 180, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T13 = keyof (() => Obj)(); ->T13 : Symbol(T13, Decl(typeCall.ts, 200, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T13 : Symbol(T13, Decl(typeCall.ts, 206, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T14 = KeyOfCall<() => Obj>; ->T14 : Symbol(T14, Decl(typeCall.ts, 201, 31)) ->KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 185, 2)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T14 : Symbol(T14, Decl(typeCall.ts, 207, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 191, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T15 = Obj['z']()['kind']; ->T15 : Symbol(T15, Decl(typeCall.ts, 202, 32)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T15 : Symbol(T15, Decl(typeCall.ts, 208, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } ->T16 : Symbol(T16, Decl(typeCall.ts, 203, 30)) ->MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 182, 59)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T16 : Symbol(T16, Decl(typeCall.ts, 209, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 188, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } ->T17 : Symbol(T17, Decl(typeCall.ts, 204, 34)) ->Strip1 : Symbol(Strip1, Decl(typeCall.ts, 187, 50)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T17 : Symbol(T17, Decl(typeCall.ts, 210, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 193, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } ->T19 : Symbol(T19, Decl(typeCall.ts, 205, 29)) ->Strip2 : Symbol(Strip2, Decl(typeCall.ts, 189, 66)) ->Obj : Symbol(Obj, Decl(typeCall.ts, 190, 91)) +>T19 : Symbol(T19, Decl(typeCall.ts, 211, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 195, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) let a1: () => string; ->a1 : Symbol(a1, Decl(typeCall.ts, 208, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 214, 3)) let b1: typeof a1(); ->b1 : Symbol(b1, Decl(typeCall.ts, 209, 3)) ->a1 : Symbol(a1, Decl(typeCall.ts, 208, 3)) +>b1 : Symbol(b1, Decl(typeCall.ts, 215, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 214, 3)) type Abc any> = T(); ->Abc : Symbol(Abc, Decl(typeCall.ts, 209, 20)) ->T : Symbol(T, Decl(typeCall.ts, 210, 9)) ->T : Symbol(T, Decl(typeCall.ts, 210, 9)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 215, 20)) +>T : Symbol(T, Decl(typeCall.ts, 216, 9)) +>T : Symbol(T, Decl(typeCall.ts, 216, 9)) let c1: Abc; ->c1 : Symbol(c1, Decl(typeCall.ts, 211, 3)) ->Abc : Symbol(Abc, Decl(typeCall.ts, 209, 20)) ->a1 : Symbol(a1, Decl(typeCall.ts, 208, 3)) +>c1 : Symbol(c1, Decl(typeCall.ts, 217, 3)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 215, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 214, 3)) declare function infer1 any>(x: T): T(); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 211, 23)) ->T : Symbol(T, Decl(typeCall.ts, 213, 24)) ->x : Symbol(x, Decl(typeCall.ts, 213, 45)) ->T : Symbol(T, Decl(typeCall.ts, 213, 24)) ->T : Symbol(T, Decl(typeCall.ts, 213, 24)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 217, 23)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) +>x : Symbol(x, Decl(typeCall.ts, 219, 45)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) infer1(null! as () => number); ->infer1 : Symbol(infer1, Decl(typeCall.ts, 211, 23)) +>infer1 : Symbol(infer1, Decl(typeCall.ts, 217, 23)) declare function infer2 any>(x: { a: T }): T(); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 214, 30)) ->T : Symbol(T, Decl(typeCall.ts, 216, 24)) ->x : Symbol(x, Decl(typeCall.ts, 216, 45)) ->a : Symbol(a, Decl(typeCall.ts, 216, 49)) ->T : Symbol(T, Decl(typeCall.ts, 216, 24)) ->T : Symbol(T, Decl(typeCall.ts, 216, 24)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 220, 30)) +>T : Symbol(T, Decl(typeCall.ts, 222, 24)) +>x : Symbol(x, Decl(typeCall.ts, 222, 45)) +>a : Symbol(a, Decl(typeCall.ts, 222, 49)) +>T : Symbol(T, Decl(typeCall.ts, 222, 24)) +>T : Symbol(T, Decl(typeCall.ts, 222, 24)) infer2(null! as { a: () => number }); ->infer2 : Symbol(infer2, Decl(typeCall.ts, 214, 30)) ->a : Symbol(a, Decl(typeCall.ts, 217, 17)) +>infer2 : Symbol(infer2, Decl(typeCall.ts, 220, 30)) +>a : Symbol(a, Decl(typeCall.ts, 223, 17)) declare function infer3(x: { a: () => T }): T; ->infer3 : Symbol(infer3, Decl(typeCall.ts, 217, 37)) ->T : Symbol(T, Decl(typeCall.ts, 219, 24)) ->x : Symbol(x, Decl(typeCall.ts, 219, 27)) ->a : Symbol(a, Decl(typeCall.ts, 219, 31)) ->T : Symbol(T, Decl(typeCall.ts, 219, 24)) ->T : Symbol(T, Decl(typeCall.ts, 219, 24)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 223, 37)) +>T : Symbol(T, Decl(typeCall.ts, 225, 24)) +>x : Symbol(x, Decl(typeCall.ts, 225, 27)) +>a : Symbol(a, Decl(typeCall.ts, 225, 31)) +>T : Symbol(T, Decl(typeCall.ts, 225, 24)) +>T : Symbol(T, Decl(typeCall.ts, 225, 24)) infer3(null! as { a: () => number }); ->infer3 : Symbol(infer3, Decl(typeCall.ts, 217, 37)) ->a : Symbol(a, Decl(typeCall.ts, 220, 17)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 223, 37)) +>a : Symbol(a, Decl(typeCall.ts, 226, 17)) const res3: number = infer3(null! as { a: () => number }); ->res3 : Symbol(res3, Decl(typeCall.ts, 221, 5)) ->infer3 : Symbol(infer3, Decl(typeCall.ts, 217, 37)) ->a : Symbol(a, Decl(typeCall.ts, 221, 38)) +>res3 : Symbol(res3, Decl(typeCall.ts, 227, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 223, 37)) +>a : Symbol(a, Decl(typeCall.ts, 227, 38)) declare function infer4(x: T, y: () => T): void; ->infer4 : Symbol(infer4, Decl(typeCall.ts, 221, 58)) ->T : Symbol(T, Decl(typeCall.ts, 223, 24)) ->x : Symbol(x, Decl(typeCall.ts, 223, 27)) ->T : Symbol(T, Decl(typeCall.ts, 223, 24)) ->y : Symbol(y, Decl(typeCall.ts, 223, 32)) ->T : Symbol(T, Decl(typeCall.ts, 223, 24)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 227, 58)) +>T : Symbol(T, Decl(typeCall.ts, 229, 24)) +>x : Symbol(x, Decl(typeCall.ts, 229, 27)) +>T : Symbol(T, Decl(typeCall.ts, 229, 24)) +>y : Symbol(y, Decl(typeCall.ts, 229, 32)) +>T : Symbol(T, Decl(typeCall.ts, 229, 24)) infer4(5, () => 5); ->infer4 : Symbol(infer4, Decl(typeCall.ts, 221, 58)) +>infer4 : Symbol(infer4, Decl(typeCall.ts, 227, 58)) function assignability(x: T, y: () => T) { ->assignability : Symbol(assignability, Decl(typeCall.ts, 224, 19)) ->T : Symbol(T, Decl(typeCall.ts, 226, 23)) ->x : Symbol(x, Decl(typeCall.ts, 226, 26)) ->T : Symbol(T, Decl(typeCall.ts, 226, 23)) ->y : Symbol(y, Decl(typeCall.ts, 226, 31)) ->T : Symbol(T, Decl(typeCall.ts, 226, 23)) +>assignability : Symbol(assignability, Decl(typeCall.ts, 230, 19)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>x : Symbol(x, Decl(typeCall.ts, 232, 26)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>y : Symbol(y, Decl(typeCall.ts, 232, 31)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) const a: T = x; ->a : Symbol(a, Decl(typeCall.ts, 227, 9)) ->T : Symbol(T, Decl(typeCall.ts, 226, 23)) ->x : Symbol(x, Decl(typeCall.ts, 226, 26)) +>a : Symbol(a, Decl(typeCall.ts, 233, 9)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>x : Symbol(x, Decl(typeCall.ts, 232, 26)) const b: T = y(); ->b : Symbol(b, Decl(typeCall.ts, 228, 9)) ->T : Symbol(T, Decl(typeCall.ts, 226, 23)) ->y : Symbol(y, Decl(typeCall.ts, 226, 31)) +>b : Symbol(b, Decl(typeCall.ts, 234, 9)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>y : Symbol(y, Decl(typeCall.ts, 232, 31)) } // function mappedAssignability(x: T, y: CallMember) { diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 85856864cf248..9ed85e470d726 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -360,7 +360,7 @@ const pathTest = path(obj, keys); // R extends any[], // I extends string = '0' // > = { 1: Reduce, 0: T }[TupleHasIndex]; -// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// // fails with error: Cannot read property 'flags' of undefined // declare function reduce< // Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, // R extends any[], @@ -413,6 +413,26 @@ type Fn3 = (v3: T3) => Fn2(Fn1(T3)); >Fn1 : Fn1 >T3 : T3 +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); +>fn3 : T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2) => (...args: any[]) => Fn2(Fn1(P1)) +>Fun1 : Fun1 +>p1 : P1 +>P1 : P1 +>T : T +>Fun2 : Fun2 +>v : T +>T : T +>P1 : P1 +>T : T +>fun1 : Fun1 +>Fun1 : Fun1 +>fun2 : Fun2 +>Fun2 : Fun2 +>args : any[] +>Fn2 : Fn2 +>Fn1 : Fn1 +>P1 : P1 + let ones = null! as 1[]; >ones : 1[] >null! as 1[] : 1[] @@ -424,12 +444,10 @@ type Fn4b = Fn3(typeof ones); >Fn3 : Fn3 >ones : 1[] -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); >Fn4c : ReadonlyArray<1> >Fn3 : Fn3 -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. let y = fn2(fn1(ones)); >y : ReadonlyArray<1> >fn2(fn1(ones)) : ReadonlyArray<1> @@ -443,6 +461,8 @@ type Y = Fn2(Fn1(1[])); >Fn2 : Fn2 >Fn1 : Fn1 +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined + interface isT { >isT : isT >T : T @@ -491,34 +511,48 @@ let neverBool: isBool(never); // 0 >neverBool : "0" >isBool : isT -type Assert = ((v: U | null | undefined) => U)(T); ->Assert : ((v: U | null | undefined) => U)(T) +type Assert = { +>Assert : { (v: null | undefined): never; (v: U): U; }(T) >T : T + + (v: null | undefined): never; +>v : null | undefined +>null : null + + (v: U): U; >U : U ->v : U | null | undefined +>v : U >U : U ->null : null >U : U + +}(T); >T : T let assert: Assert; // string >assert : string ->Assert : ((v: U | null | undefined) => U)(T) +>Assert : { (v: null | undefined): never; (v: U): U; }(T) -type Minus = ((v: U | B) => U)(A); ->Minus : ((v: B | U) => U)(A) +type Minus = { +>Minus : { (v: B): never; (v: U): U; }(A) >A : A >B : B + + (v: B): never; +>v : B +>B : B + + (v: U): U; >U : U ->v : B | U +>v : U >U : U ->B : B >U : U + +}(A); >A : A let noNumbers: Minus; // string >noNumbers : string ->Minus : ((v: B | U) => U)(A) +>Minus : { (v: B): never; (v: U): U; }(A) interface UnwrapPromise { >UnwrapPromise : UnwrapPromise @@ -548,7 +582,7 @@ declare const testUnwrap2: UnwrapPromise(Promise); >Promise : Promise declare const testUnwrap3: UnwrapPromise(boolean | Promise); ->testUnwrap3 : boolean | Promise +>testUnwrap3 : string | boolean >UnwrapPromise : UnwrapPromise >Promise : Promise @@ -599,8 +633,8 @@ declare function g(x: number): number | Promise; >Promise : Promise const testThen = myThen(pr, f, g); ->testThen : Promise> ->myThen(pr, f, g) : Promise> +>testThen : Promise +>myThen(pr, f, g) : Promise >myThen : (prom: Promise, onfulfilled?: ((value: T) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined) => Promise >pr : Promise >f : (x: number) => Promise @@ -638,8 +672,8 @@ interface Promise { } // prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; const tryProm = pr.then((x: number) => { ->tryProm : Promise> ->pr.then((x: number) => { if (x < 0) return f(x); return x;}) : Promise> +>tryProm : Promise +>pr.then((x: number) => { if (x < 0) return f(x); return x;}) : Promise >pr.then : { (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } >pr : Promise >then : { (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 65a224dbefad5..5565173295267 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -93,7 +93,7 @@ const pathTest = path(obj, keys); // R extends any[], // I extends string = '0' // > = { 1: Reduce, 0: T }[TupleHasIndex]; -// // fails with error: Cannot read property 'kind' of undefined at resolveCall +// // fails with error: Cannot read property 'flags' of undefined // declare function reduce< // Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, // R extends any[], @@ -111,13 +111,13 @@ type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; let fn1 = null! as Fn1; let fn2 = null! as Fn2; type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); let ones = null! as 1[]; type Fn4b = Fn3(typeof ones); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. type Fn4c = Fn3(1[]); -// FAILS, wanted `ReadonlyArray<1>`, got `ReadonlyArray<{}>`. let y = fn2(fn1(ones)); type Y = Fn2(Fn1(1[])); +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined interface isT { (v: never): '0'; @@ -132,10 +132,16 @@ let strBool: isBool(string); // 0 let anyBool: isBool(any); // 0 let neverBool: isBool(never); // 0 -type Assert = ((v: U | null | undefined) => U)(T); +type Assert = { + (v: null | undefined): never; + (v: U): U; +}(T); let assert: Assert; // string -type Minus = ((v: U | B) => U)(A); +type Minus = { + (v: B): never; + (v: U): U; +}(A); let noNumbers: Minus; // string interface UnwrapPromise { From e131686a5e293c50888c5bcbb84ce4b4c2c97598 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Tue, 12 Sep 2017 01:10:28 +0800 Subject: [PATCH 25/25] fix heterogeneous map test (add type param) --- tests/baselines/reference/typeCall.js | 2 +- tests/baselines/reference/typeCall.symbols | 27 ++++++++++++---------- tests/baselines/reference/typeCall.types | 15 +++++++----- tests/cases/compiler/typeCall.ts | 2 +- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js index 4acfefcfa89ca..aad62ab573620 100644 --- a/tests/baselines/reference/typeCall.js +++ b/tests/baselines/reference/typeCall.js @@ -69,7 +69,7 @@ type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols index 56ab0f23924ff..d329978856f7d 100644 --- a/tests/baselines/reference/typeCall.symbols +++ b/tests/baselines/reference/typeCall.symbols @@ -215,22 +215,25 @@ type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >b : Symbol(b, Decl(typeCall.ts, 69, 38)) >c : Symbol(c, Decl(typeCall.ts, 69, 44)) -declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; >map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) >Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) ->v : Symbol(v, Decl(typeCall.ts, 70, 33)) ->T : Symbol(T, Decl(typeCall.ts, 70, 76)) ->O : Symbol(O, Decl(typeCall.ts, 70, 46)) ->k : Symbol(k, Decl(typeCall.ts, 70, 60)) ->T : Symbol(T, Decl(typeCall.ts, 70, 76)) ->T : Symbol(T, Decl(typeCall.ts, 70, 76)) ->fn : Symbol(fn, Decl(typeCall.ts, 70, 80)) +>T : Symbol(T, Decl(typeCall.ts, 70, 33)) +>v : Symbol(v, Decl(typeCall.ts, 70, 36)) +>T : Symbol(T, Decl(typeCall.ts, 70, 33)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) +>k : Symbol(k, Decl(typeCall.ts, 70, 63)) +>T : Symbol(T, Decl(typeCall.ts, 70, 79)) +>T : Symbol(T, Decl(typeCall.ts, 70, 79)) +>fn : Symbol(fn, Decl(typeCall.ts, 70, 83)) >Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) ->obj : Symbol(obj, Decl(typeCall.ts, 70, 87)) ->O : Symbol(O, Decl(typeCall.ts, 70, 46)) ->map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>obj : Symbol(obj, Decl(typeCall.ts, 70, 90)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) +>P : Symbol(P, Decl(typeCall.ts, 70, 103)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) >Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) ->O : Symbol(O, Decl(typeCall.ts, 70, 46)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) +>P : Symbol(P, Decl(typeCall.ts, 70, 103)) let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); >z : Symbol(z, Decl(typeCall.ts, 68, 119), Decl(typeCall.ts, 71, 3)) diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types index 9ed85e470d726..fa0a3c0430290 100644 --- a/tests/baselines/reference/typeCall.types +++ b/tests/baselines/reference/typeCall.types @@ -229,9 +229,10 @@ type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); >b : 2 >c : 3 -declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); ->map : any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => map(Fn, O) +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; +>map : (v: T) => any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]); } >Fn : Fn +>T : T >v : T >T : T >O : O @@ -242,14 +243,16 @@ declare function map any, O extends { [k: string]: T }, T>( >Fn : Fn >obj : O >O : O ->map : map +>P : P +>O : O >Fn : Fn >O : O +>P : P let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); ->z : { a: [{}]; b: [{}]; c: [{}]; } ->map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }) : { a: [{}]; b: [{}]; c: [{}]; } ->map : any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => map(Fn, O) +>z : { a: [1]; b: [2]; c: [3]; } +>map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }) : { a: [1]; b: [2]; c: [3]; } +>map : (v: T) => any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]); } >(v: T) => [v] as [T] : (v: T) => [T] >T : T >v : T diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts index 5565173295267..a90749930a7c4 100644 --- a/tests/cases/compiler/typeCall.ts +++ b/tests/cases/compiler/typeCall.ts @@ -72,7 +72,7 @@ type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); -declare function map any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): map(Fn, O); +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' };