From 694c714cf594f714ca87069021a94d7d8dd75cb4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 11:56:32 -0800 Subject: [PATCH 1/7] Added test for parenthesized string literals. --- .../stringLiteralTypesAndParenthesizedExpressions01.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts new file mode 100644 index 0000000000000..7910c0e16b709 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts @@ -0,0 +1,8 @@ +// @declaration: true + +declare function myRandBool(): boolean; + +let a: "foo" = ("foo"); +let b: "foo" | "bar" = ("foo"); +let c: "foo" = (myRandBool ? "foo" : ("foo")); +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); From 38127457372b917d49d8c5ee9955ac8e1d88db42 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 12:59:39 -0800 Subject: [PATCH 2/7] Added other tests for string literal types. --- .../stringLiteralTypesAndLogicalOrExpressions01.ts | 9 +++++++++ .../types/stringLiteral/stringLiteralTypesOverloads04.ts | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts new file mode 100644 index 0000000000000..8a257ae1caf5e --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts @@ -0,0 +1,9 @@ +// @declaration: true + +declare function myRandBool(): boolean; + +let a: "foo" = "foo"; +let b = a || "foo"; +let c: "foo" = b; +let d = b || "bar"; +let e: "foo" | "bar" = d; diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts new file mode 100644 index 0000000000000..8bc2a0c94b8e6 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts @@ -0,0 +1,8 @@ +// @declaration: true + +declare function f(x: (p: "foo" | "bar") => "foo"); + +f(y => { + let z = y = "foo"; + return z; +}) \ No newline at end of file From f80a6c6e869b9f84bee99bdfd20594423f56d263 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 11:56:50 -0800 Subject: [PATCH 3/7] Accepted baselines. --- ...ngLiteralTypesAndLogicalOrExpressions01.js | 26 +++++++++++++++++ ...eralTypesAndLogicalOrExpressions01.symbols | 24 +++++++++++++++ ...iteralTypesAndLogicalOrExpressions01.types | 29 +++++++++++++++++++ ...esAndParenthesizedExpressions01.errors.txt | 17 +++++++++++ ...teralTypesAndParenthesizedExpressions01.js | 23 +++++++++++++++ .../stringLiteralTypesOverloads04.js | 18 ++++++++++++ .../stringLiteralTypesOverloads04.symbols | 19 ++++++++++++ .../stringLiteralTypesOverloads04.types | 23 +++++++++++++++ 8 files changed, 179 insertions(+) create mode 100644 tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js create mode 100644 tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads04.js create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads04.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads04.types diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js new file mode 100644 index 0000000000000..479256b18b7e5 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js @@ -0,0 +1,26 @@ +//// [stringLiteralTypesAndLogicalOrExpressions01.ts] + +declare function myRandBool(): boolean; + +let a: "foo" = "foo"; +let b = a || "foo"; +let c: "foo" = b; +let d = b || "bar"; +let e: "foo" | "bar" = d; + + +//// [stringLiteralTypesAndLogicalOrExpressions01.js] +var a = "foo"; +var b = a || "foo"; +var c = b; +var d = b || "bar"; +var e = d; + + +//// [stringLiteralTypesAndLogicalOrExpressions01.d.ts] +declare function myRandBool(): boolean; +declare let a: "foo"; +declare let b: "foo"; +declare let c: "foo"; +declare let d: "foo" | "bar"; +declare let e: "foo" | "bar"; diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols new file mode 100644 index 0000000000000..2a9f28e85a5ca --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 0, 0)) + +let a: "foo" = "foo"; +>a : Symbol(a, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 3, 3)) + +let b = a || "foo"; +>b : Symbol(b, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 4, 3)) +>a : Symbol(a, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 3, 3)) + +let c: "foo" = b; +>c : Symbol(c, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 5, 3)) +>b : Symbol(b, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 4, 3)) + +let d = b || "bar"; +>d : Symbol(d, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 6, 3)) +>b : Symbol(b, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 4, 3)) + +let e: "foo" | "bar" = d; +>e : Symbol(e, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 7, 3)) +>d : Symbol(d, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 6, 3)) + diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types new file mode 100644 index 0000000000000..ddc79b818579e --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : () => boolean + +let a: "foo" = "foo"; +>a : "foo" +>"foo" : "foo" + +let b = a || "foo"; +>b : "foo" +>a || "foo" : "foo" +>a : "foo" +>"foo" : "foo" + +let c: "foo" = b; +>c : "foo" +>b : "foo" + +let d = b || "bar"; +>d : "foo" | "bar" +>b || "bar" : "foo" | "bar" +>b : "foo" +>"bar" : "bar" + +let e: "foo" | "bar" = d; +>e : "foo" | "bar" +>d : "foo" | "bar" + diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt new file mode 100644 index 0000000000000..93d8a213d0fee --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(4,5): error TS2322: Type 'string' is not assignable to type '"foo"'. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(6,5): error TS2322: Type 'string' is not assignable to type '"foo"'. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts (2 errors) ==== + + declare function myRandBool(): boolean; + + let a: "foo" = ("foo"); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"foo"'. + let b: "foo" | "bar" = ("foo"); + let c: "foo" = (myRandBool ? "foo" : ("foo")); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"foo"'. + let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); + \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js new file mode 100644 index 0000000000000..1fe1225c6f40d --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js @@ -0,0 +1,23 @@ +//// [stringLiteralTypesAndParenthesizedExpressions01.ts] + +declare function myRandBool(): boolean; + +let a: "foo" = ("foo"); +let b: "foo" | "bar" = ("foo"); +let c: "foo" = (myRandBool ? "foo" : ("foo")); +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); + + +//// [stringLiteralTypesAndParenthesizedExpressions01.js] +var a = ("foo"); +var b = ("foo"); +var c = (myRandBool ? "foo" : ("foo")); +var d = (myRandBool ? "foo" : ("bar")); + + +//// [stringLiteralTypesAndParenthesizedExpressions01.d.ts] +declare function myRandBool(): boolean; +declare let a: "foo"; +declare let b: "foo" | "bar"; +declare let c: "foo"; +declare let d: "foo" | "bar"; diff --git a/tests/baselines/reference/stringLiteralTypesOverloads04.js b/tests/baselines/reference/stringLiteralTypesOverloads04.js new file mode 100644 index 0000000000000..fd10ac986a9d5 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads04.js @@ -0,0 +1,18 @@ +//// [stringLiteralTypesOverloads04.ts] + +declare function f(x: (p: "foo" | "bar") => "foo"); + +f(y => { + let z = y = "foo"; + return z; +}) + +//// [stringLiteralTypesOverloads04.js] +f(function (y) { + var z = y = "foo"; + return z; +}); + + +//// [stringLiteralTypesOverloads04.d.ts] +declare function f(x: (p: "foo" | "bar") => "foo"): any; diff --git a/tests/baselines/reference/stringLiteralTypesOverloads04.symbols b/tests/baselines/reference/stringLiteralTypesOverloads04.symbols new file mode 100644 index 0000000000000..9f468b8bd9502 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads04.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts === + +declare function f(x: (p: "foo" | "bar") => "foo"); +>f : Symbol(f, Decl(stringLiteralTypesOverloads04.ts, 0, 0)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads04.ts, 1, 19)) +>p : Symbol(p, Decl(stringLiteralTypesOverloads04.ts, 1, 23)) + +f(y => { +>f : Symbol(f, Decl(stringLiteralTypesOverloads04.ts, 0, 0)) +>y : Symbol(y, Decl(stringLiteralTypesOverloads04.ts, 3, 2)) + + let z = y = "foo"; +>z : Symbol(z, Decl(stringLiteralTypesOverloads04.ts, 4, 7)) +>y : Symbol(y, Decl(stringLiteralTypesOverloads04.ts, 3, 2)) + + return z; +>z : Symbol(z, Decl(stringLiteralTypesOverloads04.ts, 4, 7)) + +}) diff --git a/tests/baselines/reference/stringLiteralTypesOverloads04.types b/tests/baselines/reference/stringLiteralTypesOverloads04.types new file mode 100644 index 0000000000000..32d316494ca5e --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads04.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts === + +declare function f(x: (p: "foo" | "bar") => "foo"); +>f : (x: (p: "foo" | "bar") => "foo") => any +>x : (p: "foo" | "bar") => "foo" +>p : "foo" | "bar" + +f(y => { +>f(y => { let z = y = "foo"; return z;}) : any +>f : (x: (p: "foo" | "bar") => "foo") => any +>y => { let z = y = "foo"; return z;} : (y: "foo" | "bar") => "foo" +>y : "foo" | "bar" + + let z = y = "foo"; +>z : "foo" +>y = "foo" : "foo" +>y : "foo" | "bar" +>"foo" : "foo" + + return z; +>z : "foo" + +}) From 2a370c9aa7ad5d1d12fb83508f99cd1f08b42d2b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 14:40:19 -0800 Subject: [PATCH 4/7] Added tests for string literal types used as generic constraints. --- ...LiteralTypesAsTypeParameterConstraint01.ts | 19 +++++++++++++++++++ ...LiteralTypesAsTypeParameterConstraint02.ts | 8 ++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts new file mode 100644 index 0000000000000..53f516f4209b9 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts @@ -0,0 +1,19 @@ +// @declaration: true + +function foo(f: (x: T) => T) { + return f; +} + +function bar(f: (x: T) => T) { + return f; +} + +let f = foo(x => x); +let fResult = f("foo"); + +let g = foo((x => x)); +let gResult = g("foo"); + +let h = bar(x => x); +let hResult = h("foo"); +hResult = h("bar"); \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts new file mode 100644 index 0000000000000..fb3a019402dae --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts @@ -0,0 +1,8 @@ +// @declaration: true + +function foo(f: (x: T) => T) { + return f; +} + +let f = foo((y: "foo" | "bar") => y === "foo" ? y : "foo"); +let fResult = f("foo"); \ No newline at end of file From 9d3d49d636e69715c45bcd5d3632531a61874927 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 16:17:28 -0800 Subject: [PATCH 5/7] Only get the apparent type when necessary. --- 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 e0e9a6e620f54..4fe04cae13a46 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6966,7 +6966,7 @@ namespace ts { else if (operator === SyntaxKind.BarBarToken) { // When an || expression has a contextual type, the operands are contextually typed by that type. When an || // expression has no contextual type, the right operand is contextually typed by the type of the left operand. - let type = getApparentTypeOfContextualType(binaryExpression); + let type = getContextualType(binaryExpression); if (!type && node === binaryExpression.right) { type = checkExpression(binaryExpression.left); } @@ -7081,7 +7081,7 @@ namespace ts { // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type. function getContextualTypeForConditionalOperand(node: Expression): Type { const conditional = node.parent; - return node === conditional.whenTrue || node === conditional.whenFalse ? getApparentTypeOfContextualType(conditional) : undefined; + return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined; } function getContextualTypeForJsxExpression(expr: JsxExpression | JsxSpreadAttribute): Type { @@ -7160,7 +7160,7 @@ namespace ts { Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression); return getContextualTypeForSubstitutionExpression(parent.parent, node); case SyntaxKind.ParenthesizedExpression: - return getApparentTypeOfContextualType(parent); + return getContextualType(parent); case SyntaxKind.JsxExpression: case SyntaxKind.JsxSpreadAttribute: return getContextualTypeForJsxExpression(parent); From ce455dac2b3ce3b0255be7441b2f84a24f9369b1 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 22:43:07 -0800 Subject: [PATCH 6/7] Accepted baselines. --- ...esAndParenthesizedExpressions01.errors.txt | 17 ----- ...TypesAndParenthesizedExpressions01.symbols | 19 +++++ ...alTypesAndParenthesizedExpressions01.types | 33 ++++++++ ...LiteralTypesAsTypeParameterConstraint01.js | 68 +++++++++++++++++ ...alTypesAsTypeParameterConstraint01.symbols | 60 +++++++++++++++ ...eralTypesAsTypeParameterConstraint01.types | 76 +++++++++++++++++++ ...ypesAsTypeParameterConstraint02.errors.txt | 15 ++++ ...LiteralTypesAsTypeParameterConstraint02.js | 21 +++++ 8 files changed, 292 insertions(+), 17 deletions(-) delete mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt deleted file mode 100644 index 93d8a213d0fee..0000000000000 --- a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt +++ /dev/null @@ -1,17 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(4,5): error TS2322: Type 'string' is not assignable to type '"foo"'. -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(6,5): error TS2322: Type 'string' is not assignable to type '"foo"'. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts (2 errors) ==== - - declare function myRandBool(): boolean; - - let a: "foo" = ("foo"); - ~ -!!! error TS2322: Type 'string' is not assignable to type '"foo"'. - let b: "foo" | "bar" = ("foo"); - let c: "foo" = (myRandBool ? "foo" : ("foo")); - ~ -!!! error TS2322: Type 'string' is not assignable to type '"foo"'. - let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); - \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols new file mode 100644 index 0000000000000..2206a5185c1af --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 0, 0)) + +let a: "foo" = ("foo"); +>a : Symbol(a, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 3, 3)) + +let b: "foo" | "bar" = ("foo"); +>b : Symbol(b, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 4, 3)) + +let c: "foo" = (myRandBool ? "foo" : ("foo")); +>c : Symbol(c, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 5, 3)) +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 0, 0)) + +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); +>d : Symbol(d, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 6, 3)) +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 0, 0)) + diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types new file mode 100644 index 0000000000000..0bb2e1dd3c7b8 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : () => boolean + +let a: "foo" = ("foo"); +>a : "foo" +>("foo") : "foo" +>"foo" : "foo" + +let b: "foo" | "bar" = ("foo"); +>b : "foo" | "bar" +>("foo") : "foo" +>"foo" : "foo" + +let c: "foo" = (myRandBool ? "foo" : ("foo")); +>c : "foo" +>(myRandBool ? "foo" : ("foo")) : "foo" +>myRandBool ? "foo" : ("foo") : "foo" +>myRandBool : () => boolean +>"foo" : "foo" +>("foo") : "foo" +>"foo" : "foo" + +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); +>d : "foo" | "bar" +>(myRandBool ? "foo" : ("bar")) : "foo" | "bar" +>myRandBool ? "foo" : ("bar") : "foo" | "bar" +>myRandBool : () => boolean +>"foo" : "foo" +>("bar") : "bar" +>"bar" : "bar" + diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js new file mode 100644 index 0000000000000..558f6bdf4c2fd --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js @@ -0,0 +1,68 @@ +//// [stringLiteralTypesAsTypeParameterConstraint01.ts] + +function foo(f: (x: T) => T) { + return f; +} + +function bar(f: (x: T) => T) { + return f; +} + +let f = foo(x => x); +let fResult = f("foo"); + +let g = foo((x => x)); +let gResult = g("foo"); + +let h = bar(x => x); +let hResult = h("foo"); +hResult = h("bar"); + +//// [stringLiteralTypesAsTypeParameterConstraint01.js] +function foo(f) { + return f; +} +function bar(f) { + return f; +} +var f = foo(function (x) { return x; }); +var fResult = f("foo"); +var g = foo((function (x) { return x; })); +var gResult = g("foo"); +var h = bar(function (x) { return x; }); +var hResult = h("foo"); +hResult = h("bar"); + + +//// [stringLiteralTypesAsTypeParameterConstraint01.d.ts] +declare function foo(f: (x: T) => T): (x: T) => T; +declare function bar(f: (x: T) => T): (x: T) => T; +declare let f: (x: "foo") => "foo"; +declare let fResult: "foo"; +declare let g: (x: "foo") => "foo"; +declare let gResult: "foo"; +declare let h: (x: "foo" | "bar") => "foo" | "bar"; +declare let hResult: "foo" | "bar"; + + +//// [DtsFileErrors] + + +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.d.ts(3,16): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.d.ts(5,16): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.d.ts (2 errors) ==== + declare function foo(f: (x: T) => T): (x: T) => T; + declare function bar(f: (x: T) => T): (x: T) => T; + declare let f: (x: "foo") => "foo"; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + declare let fResult: "foo"; + declare let g: (x: "foo") => "foo"; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + declare let gResult: "foo"; + declare let h: (x: "foo" | "bar") => "foo" | "bar"; + declare let hResult: "foo" | "bar"; + \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols new file mode 100644 index 0000000000000..fd633b6e4d912 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols @@ -0,0 +1,60 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts === + +function foo(f: (x: T) => T) { +>foo : Symbol(foo, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 0, 0)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 13)) +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 30)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 34)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 13)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 13)) + + return f; +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 30)) +} + +function bar(f: (x: T) => T) { +>bar : Symbol(bar, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 3, 1)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 13)) +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 38)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 42)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 13)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 13)) + + return f; +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 38)) +} + +let f = foo(x => x); +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 3)) +>foo : Symbol(foo, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 0, 0)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 12)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 12)) + +let fResult = f("foo"); +>fResult : Symbol(fResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 10, 3)) +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 3)) + +let g = foo((x => x)); +>g : Symbol(g, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 3)) +>foo : Symbol(foo, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 0, 0)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 13)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 13)) + +let gResult = g("foo"); +>gResult : Symbol(gResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 13, 3)) +>g : Symbol(g, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 3)) + +let h = bar(x => x); +>h : Symbol(h, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 3)) +>bar : Symbol(bar, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 3, 1)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 12)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 12)) + +let hResult = h("foo"); +>hResult : Symbol(hResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 16, 3)) +>h : Symbol(h, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 3)) + +hResult = h("bar"); +>hResult : Symbol(hResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 16, 3)) +>h : Symbol(h, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 3)) + diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types new file mode 100644 index 0000000000000..fe9163fc81911 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types @@ -0,0 +1,76 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts === + +function foo(f: (x: T) => T) { +>foo : (f: (x: T) => T) => (x: T) => T +>T : T +>f : (x: T) => T +>x : T +>T : T +>T : T + + return f; +>f : (x: T) => T +} + +function bar(f: (x: T) => T) { +>bar : (f: (x: T) => T) => (x: T) => T +>T : T +>f : (x: T) => T +>x : T +>T : T +>T : T + + return f; +>f : (x: T) => T +} + +let f = foo(x => x); +>f : (x: "foo") => "foo" +>foo(x => x) : (x: "foo") => "foo" +>foo : (f: (x: T) => T) => (x: T) => T +>x => x : (x: "foo") => "foo" +>x : "foo" +>x : "foo" + +let fResult = f("foo"); +>fResult : "foo" +>f("foo") : "foo" +>f : (x: "foo") => "foo" +>"foo" : "foo" + +let g = foo((x => x)); +>g : (x: "foo") => "foo" +>foo((x => x)) : (x: "foo") => "foo" +>foo : (f: (x: T) => T) => (x: T) => T +>(x => x) : (x: "foo") => "foo" +>x => x : (x: "foo") => "foo" +>x : "foo" +>x : "foo" + +let gResult = g("foo"); +>gResult : "foo" +>g("foo") : "foo" +>g : (x: "foo") => "foo" +>"foo" : "foo" + +let h = bar(x => x); +>h : (x: "foo" | "bar") => "foo" | "bar" +>bar(x => x) : (x: "foo" | "bar") => "foo" | "bar" +>bar : (f: (x: T) => T) => (x: T) => T +>x => x : (x: "foo" | "bar") => "foo" | "bar" +>x : "foo" | "bar" +>x : "foo" | "bar" + +let hResult = h("foo"); +>hResult : "foo" | "bar" +>h("foo") : "foo" | "bar" +>h : (x: "foo" | "bar") => "foo" | "bar" +>"foo" : "foo" + +hResult = h("bar"); +>hResult = h("bar") : "foo" | "bar" +>hResult : "foo" | "bar" +>h("bar") : "foo" | "bar" +>h : (x: "foo" | "bar") => "foo" | "bar" +>"bar" : "bar" + diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt new file mode 100644 index 0000000000000..ed6450ad3293f --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts(6,13): error TS2345: Argument of type '(y: "foo" | "bar") => string' is not assignable to parameter of type '(x: "foo") => "foo"'. + Type 'string' is not assignable to type '"foo"'. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts (1 errors) ==== + + function foo(f: (x: T) => T) { + return f; + } + + let f = foo((y: "foo" | "bar") => y === "foo" ? y : "foo"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '(y: "foo" | "bar") => string' is not assignable to parameter of type '(x: "foo") => "foo"'. +!!! error TS2345: Type 'string' is not assignable to type '"foo"'. + let fResult = f("foo"); \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js new file mode 100644 index 0000000000000..c024ac6bc43b2 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js @@ -0,0 +1,21 @@ +//// [stringLiteralTypesAsTypeParameterConstraint02.ts] + +function foo(f: (x: T) => T) { + return f; +} + +let f = foo((y: "foo" | "bar") => y === "foo" ? y : "foo"); +let fResult = f("foo"); + +//// [stringLiteralTypesAsTypeParameterConstraint02.js] +function foo(f) { + return f; +} +var f = foo(function (y) { return y === "foo" ? y : "foo"; }); +var fResult = f("foo"); + + +//// [stringLiteralTypesAsTypeParameterConstraint02.d.ts] +declare function foo(f: (x: T) => T): (x: T) => T; +declare let f: any; +declare let fResult: any; From b93394a7acc9b56cd9e97dccd311c2419762b76d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 23:15:48 -0800 Subject: [PATCH 7/7] Added to comment. --- src/compiler/checker.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4fe04cae13a46..8f751f25523b6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7114,9 +7114,16 @@ namespace ts { /** * Woah! Do you really want to use this function? * - * Unless you're trying to get the *non-apparent* type for a value-literal type, + * Unless you're trying to get the *non-apparent* type for a + * value-literal type or you're authoring relevant portions of this algorithm, * you probably meant to use 'getApparentTypeOfContextualType'. - * Otherwise this is slightly less useful. + * Otherwise this may not be very useful. + * + * In cases where you *are* working on this function, you should understand + * when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContetxualType'. + * + * - Use 'getContextualType' when you are simply going to propagate the result to the expression. + * - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type. * * @param node the expression whose contextual type will be returned. * @returns the contextual type of an expression.