mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #24310 from Microsoft/nonWideningLiteralInferences
Non-widening literal type inferences
This commit is contained in:
@@ -9286,8 +9286,10 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function getRegularTypeOfLiteralType(type: Type) {
|
||||
return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType : type;
|
||||
function getRegularTypeOfLiteralType(type: Type): Type {
|
||||
return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType :
|
||||
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) :
|
||||
type;
|
||||
}
|
||||
|
||||
function getLiteralType(value: string | number, enumId?: number, symbol?: Symbol) {
|
||||
@@ -12774,10 +12776,12 @@ namespace ts {
|
||||
// all inferences were made to top-level occurrences of the type parameter, and
|
||||
// the type parameter has no constraint or its constraint includes no primitive or literal types, and
|
||||
// the type parameter was fixed during inference or does not occur at top-level in the return type.
|
||||
const widenLiteralTypes = inference.topLevel &&
|
||||
!hasPrimitiveConstraint(inference.typeParameter) &&
|
||||
const primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter);
|
||||
const widenLiteralTypes = !primitiveConstraint && inference.topLevel &&
|
||||
(inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter));
|
||||
const baseCandidates = widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) : candidates;
|
||||
const baseCandidates = primitiveConstraint ? sameMap(candidates, getRegularTypeOfLiteralType) :
|
||||
widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) :
|
||||
candidates;
|
||||
// If all inferences were made from contravariant positions, infer a common subtype. Otherwise, if
|
||||
// union types were requested or if all inferences were made from the return type position, infer a
|
||||
// union type. Otherwise, infer a common supertype.
|
||||
|
||||
@@ -30,7 +30,7 @@ var derived2: Derived2;
|
||||
|
||||
var r2 = true ? 1 : '';
|
||||
>r2 : string | number
|
||||
>true ? 1 : '' : 1 | ""
|
||||
>true ? 1 : '' : "" | 1
|
||||
>true : true
|
||||
>1 : 1
|
||||
>'' : ""
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ var i: I<string>;
|
||||
>I : I<T>
|
||||
|
||||
var y = i(""); // y should be string
|
||||
>y : string
|
||||
>y : ""
|
||||
>i("") : ""
|
||||
>i : I<string>
|
||||
>"" : ""
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
=== tests/cases/compiler/conditionalExpression1.ts ===
|
||||
var x: boolean = (true ? 1 : ""); // should be an error
|
||||
>x : boolean
|
||||
>(true ? 1 : "") : 1 | ""
|
||||
>true ? 1 : "" : 1 | ""
|
||||
>(true ? 1 : "") : "" | 1
|
||||
>true ? 1 : "" : "" | 1
|
||||
>true : true
|
||||
>1 : 1
|
||||
>"" : ""
|
||||
|
||||
@@ -15,7 +15,7 @@ var b = false ? undefined : 0;
|
||||
|
||||
var c = false ? 1 : 0;
|
||||
>c : number
|
||||
>false ? 1 : 0 : 1 | 0
|
||||
>false ? 1 : 0 : 0 | 1
|
||||
>false : false
|
||||
>1 : 1
|
||||
>0 : 0
|
||||
|
||||
@@ -218,7 +218,7 @@ var result10: (t: X) => any = true ? (m) => m.propertyX1 : (n) => n.propertyX2;
|
||||
//Expr1 and Expr2 are literals
|
||||
var result11: any = true ? 1 : 'string';
|
||||
>result11 : any
|
||||
>true ? 1 : 'string' : 1 | "string"
|
||||
>true ? 1 : 'string' : "string" | 1
|
||||
>true : true
|
||||
>1 : 1
|
||||
>'string' : "string"
|
||||
|
||||
@@ -589,8 +589,8 @@ function zeroOf<T extends number | string | boolean>(value: T) {
|
||||
><ZeroOf<T>>(typeof value === "number" ? 0 : typeof value === "string" ? "" : false) : ZeroOf<T>
|
||||
>ZeroOf : ZeroOf<T>
|
||||
>T : T
|
||||
>(typeof value === "number" ? 0 : typeof value === "string" ? "" : false) : false | 0 | ""
|
||||
>typeof value === "number" ? 0 : typeof value === "string" ? "" : false : false | 0 | ""
|
||||
>(typeof value === "number" ? 0 : typeof value === "string" ? "" : false) : false | "" | 0
|
||||
>typeof value === "number" ? 0 : typeof value === "string" ? "" : false : false | "" | 0
|
||||
>typeof value === "number" : boolean
|
||||
>typeof value : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>value : T
|
||||
|
||||
@@ -24,7 +24,7 @@ var y = [() => new c()];
|
||||
var k: (() => c) | string = (() => new c()) || "";
|
||||
>k : string | (() => c)
|
||||
>c : c
|
||||
>(() => new c()) || "" : (() => c) | ""
|
||||
>(() => new c()) || "" : "" | (() => c)
|
||||
>(() => new c()) : () => c
|
||||
>() => new c() : () => c
|
||||
>new c() : c
|
||||
|
||||
@@ -60,6 +60,18 @@ function f5() {
|
||||
let v4 = c4;
|
||||
}
|
||||
|
||||
declare function widening<T>(x: T): T;
|
||||
declare function nonWidening<T extends string | number | symbol>(x: T): T;
|
||||
|
||||
function f6(cond: boolean) {
|
||||
let x1 = widening('a');
|
||||
let x2 = widening(10);
|
||||
let x3 = widening(cond ? 'a' : 10);
|
||||
let y1 = nonWidening('a');
|
||||
let y2 = nonWidening(10);
|
||||
let y3 = nonWidening(cond ? 'a' : 10);
|
||||
}
|
||||
|
||||
// Repro from #10898
|
||||
|
||||
type FAILURE = "FAILURE";
|
||||
@@ -95,10 +107,33 @@ type TestEvent = "onmouseover" | "onmouseout";
|
||||
|
||||
function onMouseOver(): TestEvent { return "onmouseover"; }
|
||||
|
||||
let x = onMouseOver();
|
||||
let x = onMouseOver();
|
||||
|
||||
// Repro from #23649
|
||||
|
||||
export function Set<K extends string>(...keys: K[]): Record<K, true | undefined> {
|
||||
const result = {} as Record<K, true | undefined>
|
||||
keys.forEach(key => result[key] = true)
|
||||
return result
|
||||
}
|
||||
|
||||
export function keys<K extends string, V>(obj: Record<K, V>): K[] {
|
||||
return Object.keys(obj) as K[]
|
||||
}
|
||||
|
||||
type Obj = { code: LangCode }
|
||||
|
||||
const langCodeSet = Set('fr', 'en', 'es', 'it', 'nl')
|
||||
export type LangCode = keyof typeof langCodeSet
|
||||
export const langCodes = keys(langCodeSet)
|
||||
|
||||
const arr: Obj[] = langCodes.map(code => ({ code }))
|
||||
|
||||
|
||||
//// [literalTypeWidening.js]
|
||||
"use strict";
|
||||
// Widening vs. non-widening literal types
|
||||
exports.__esModule = true;
|
||||
function f1() {
|
||||
var c1 = "hello"; // Widening type "hello"
|
||||
var v1 = c1; // Type string
|
||||
@@ -153,6 +188,14 @@ function f5() {
|
||||
var c4 = "foo";
|
||||
var v4 = c4;
|
||||
}
|
||||
function f6(cond) {
|
||||
var x1 = widening('a');
|
||||
var x2 = widening(10);
|
||||
var x3 = widening(cond ? 'a' : 10);
|
||||
var y1 = nonWidening('a');
|
||||
var y2 = nonWidening(10);
|
||||
var y3 = nonWidening(cond ? 'a' : 10);
|
||||
}
|
||||
var FAILURE = "FAILURE";
|
||||
function doWork() {
|
||||
return FAILURE;
|
||||
@@ -172,3 +215,21 @@ if (isSuccess(result)) {
|
||||
}
|
||||
function onMouseOver() { return "onmouseover"; }
|
||||
var x = onMouseOver();
|
||||
// Repro from #23649
|
||||
function Set() {
|
||||
var keys = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
keys[_i] = arguments[_i];
|
||||
}
|
||||
var result = {};
|
||||
keys.forEach(function (key) { return result[key] = true; });
|
||||
return result;
|
||||
}
|
||||
exports.Set = Set;
|
||||
function keys(obj) {
|
||||
return Object.keys(obj);
|
||||
}
|
||||
exports.keys = keys;
|
||||
var langCodeSet = Set('fr', 'en', 'es', 'it', 'nl');
|
||||
exports.langCodes = keys(langCodeSet);
|
||||
var arr = exports.langCodes.map(function (code) { return ({ code: code }); });
|
||||
|
||||
@@ -197,89 +197,206 @@ function f5() {
|
||||
>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 57, 9))
|
||||
}
|
||||
|
||||
declare function widening<T>(x: T): T;
|
||||
>widening : Symbol(widening, Decl(literalTypeWidening.ts, 59, 1))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 61, 26))
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 61, 29))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 61, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 61, 26))
|
||||
|
||||
declare function nonWidening<T extends string | number | symbol>(x: T): T;
|
||||
>nonWidening : Symbol(nonWidening, Decl(literalTypeWidening.ts, 61, 38))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 62, 29))
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 62, 65))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 62, 29))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 62, 29))
|
||||
|
||||
function f6(cond: boolean) {
|
||||
>f6 : Symbol(f6, Decl(literalTypeWidening.ts, 62, 74))
|
||||
>cond : Symbol(cond, Decl(literalTypeWidening.ts, 64, 12))
|
||||
|
||||
let x1 = widening('a');
|
||||
>x1 : Symbol(x1, Decl(literalTypeWidening.ts, 65, 7))
|
||||
>widening : Symbol(widening, Decl(literalTypeWidening.ts, 59, 1))
|
||||
|
||||
let x2 = widening(10);
|
||||
>x2 : Symbol(x2, Decl(literalTypeWidening.ts, 66, 7))
|
||||
>widening : Symbol(widening, Decl(literalTypeWidening.ts, 59, 1))
|
||||
|
||||
let x3 = widening(cond ? 'a' : 10);
|
||||
>x3 : Symbol(x3, Decl(literalTypeWidening.ts, 67, 7))
|
||||
>widening : Symbol(widening, Decl(literalTypeWidening.ts, 59, 1))
|
||||
>cond : Symbol(cond, Decl(literalTypeWidening.ts, 64, 12))
|
||||
|
||||
let y1 = nonWidening('a');
|
||||
>y1 : Symbol(y1, Decl(literalTypeWidening.ts, 68, 7))
|
||||
>nonWidening : Symbol(nonWidening, Decl(literalTypeWidening.ts, 61, 38))
|
||||
|
||||
let y2 = nonWidening(10);
|
||||
>y2 : Symbol(y2, Decl(literalTypeWidening.ts, 69, 7))
|
||||
>nonWidening : Symbol(nonWidening, Decl(literalTypeWidening.ts, 61, 38))
|
||||
|
||||
let y3 = nonWidening(cond ? 'a' : 10);
|
||||
>y3 : Symbol(y3, Decl(literalTypeWidening.ts, 70, 7))
|
||||
>nonWidening : Symbol(nonWidening, Decl(literalTypeWidening.ts, 61, 38))
|
||||
>cond : Symbol(cond, Decl(literalTypeWidening.ts, 64, 12))
|
||||
}
|
||||
|
||||
// Repro from #10898
|
||||
|
||||
type FAILURE = "FAILURE";
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 71, 1), Decl(literalTypeWidening.ts, 76, 5))
|
||||
|
||||
const FAILURE = "FAILURE";
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 71, 1), Decl(literalTypeWidening.ts, 76, 5))
|
||||
|
||||
type Result<T> = T | FAILURE;
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 66, 12))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 66, 12))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5))
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 76, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 78, 12))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 78, 12))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 71, 1), Decl(literalTypeWidening.ts, 76, 5))
|
||||
|
||||
function doWork<T>(): Result<T> {
|
||||
>doWork : Symbol(doWork, Decl(literalTypeWidening.ts, 66, 29))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 68, 16))
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 68, 16))
|
||||
>doWork : Symbol(doWork, Decl(literalTypeWidening.ts, 78, 29))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 80, 16))
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 76, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 80, 16))
|
||||
|
||||
return FAILURE;
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 71, 1), Decl(literalTypeWidening.ts, 76, 5))
|
||||
}
|
||||
|
||||
function isSuccess<T>(result: Result<T>): result is T {
|
||||
>isSuccess : Symbol(isSuccess, Decl(literalTypeWidening.ts, 70, 1))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 72, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 72, 22))
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 72, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 72, 22))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 72, 19))
|
||||
>isSuccess : Symbol(isSuccess, Decl(literalTypeWidening.ts, 82, 1))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 84, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 22))
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 76, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 84, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 22))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 84, 19))
|
||||
|
||||
return !isFailure(result);
|
||||
>isFailure : Symbol(isFailure, Decl(literalTypeWidening.ts, 74, 1))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 72, 22))
|
||||
>isFailure : Symbol(isFailure, Decl(literalTypeWidening.ts, 86, 1))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 22))
|
||||
}
|
||||
|
||||
function isFailure<T>(result: Result<T>): result is FAILURE {
|
||||
>isFailure : Symbol(isFailure, Decl(literalTypeWidening.ts, 74, 1))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 76, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 76, 22))
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 76, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 76, 22))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5))
|
||||
>isFailure : Symbol(isFailure, Decl(literalTypeWidening.ts, 86, 1))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 88, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 88, 22))
|
||||
>Result : Symbol(Result, Decl(literalTypeWidening.ts, 76, 26))
|
||||
>T : Symbol(T, Decl(literalTypeWidening.ts, 88, 19))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 88, 22))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 71, 1), Decl(literalTypeWidening.ts, 76, 5))
|
||||
|
||||
return result === FAILURE;
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 76, 22))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 88, 22))
|
||||
>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 71, 1), Decl(literalTypeWidening.ts, 76, 5))
|
||||
}
|
||||
|
||||
function increment(x: number): number {
|
||||
>increment : Symbol(increment, Decl(literalTypeWidening.ts, 78, 1))
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 80, 19))
|
||||
>increment : Symbol(increment, Decl(literalTypeWidening.ts, 90, 1))
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 92, 19))
|
||||
|
||||
return x + 1;
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 80, 19))
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 92, 19))
|
||||
}
|
||||
|
||||
let result = doWork<number>();
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 3))
|
||||
>doWork : Symbol(doWork, Decl(literalTypeWidening.ts, 66, 29))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 96, 3))
|
||||
>doWork : Symbol(doWork, Decl(literalTypeWidening.ts, 78, 29))
|
||||
|
||||
if (isSuccess(result)) {
|
||||
>isSuccess : Symbol(isSuccess, Decl(literalTypeWidening.ts, 70, 1))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 3))
|
||||
>isSuccess : Symbol(isSuccess, Decl(literalTypeWidening.ts, 82, 1))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 96, 3))
|
||||
|
||||
increment(result);
|
||||
>increment : Symbol(increment, Decl(literalTypeWidening.ts, 78, 1))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 3))
|
||||
>increment : Symbol(increment, Decl(literalTypeWidening.ts, 90, 1))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 96, 3))
|
||||
}
|
||||
|
||||
// Repro from #10898
|
||||
|
||||
type TestEvent = "onmouseover" | "onmouseout";
|
||||
>TestEvent : Symbol(TestEvent, Decl(literalTypeWidening.ts, 88, 1))
|
||||
>TestEvent : Symbol(TestEvent, Decl(literalTypeWidening.ts, 100, 1))
|
||||
|
||||
function onMouseOver(): TestEvent { return "onmouseover"; }
|
||||
>onMouseOver : Symbol(onMouseOver, Decl(literalTypeWidening.ts, 92, 46))
|
||||
>TestEvent : Symbol(TestEvent, Decl(literalTypeWidening.ts, 88, 1))
|
||||
>onMouseOver : Symbol(onMouseOver, Decl(literalTypeWidening.ts, 104, 46))
|
||||
>TestEvent : Symbol(TestEvent, Decl(literalTypeWidening.ts, 100, 1))
|
||||
|
||||
let x = onMouseOver();
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 96, 3))
|
||||
>onMouseOver : Symbol(onMouseOver, Decl(literalTypeWidening.ts, 92, 46))
|
||||
>x : Symbol(x, Decl(literalTypeWidening.ts, 108, 3))
|
||||
>onMouseOver : Symbol(onMouseOver, Decl(literalTypeWidening.ts, 104, 46))
|
||||
|
||||
// Repro from #23649
|
||||
|
||||
export function Set<K extends string>(...keys: K[]): Record<K, true | undefined> {
|
||||
>Set : Symbol(Set, Decl(literalTypeWidening.ts, 108, 22))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 112, 20))
|
||||
>keys : Symbol(keys, Decl(literalTypeWidening.ts, 112, 38))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 112, 20))
|
||||
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 112, 20))
|
||||
|
||||
const result = {} as Record<K, true | undefined>
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 113, 7))
|
||||
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 112, 20))
|
||||
|
||||
keys.forEach(key => result[key] = true)
|
||||
>keys.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
|
||||
>keys : Symbol(keys, Decl(literalTypeWidening.ts, 112, 38))
|
||||
>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
|
||||
>key : Symbol(key, Decl(literalTypeWidening.ts, 114, 15))
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 113, 7))
|
||||
>key : Symbol(key, Decl(literalTypeWidening.ts, 114, 15))
|
||||
|
||||
return result
|
||||
>result : Symbol(result, Decl(literalTypeWidening.ts, 113, 7))
|
||||
}
|
||||
|
||||
export function keys<K extends string, V>(obj: Record<K, V>): K[] {
|
||||
>keys : Symbol(keys, Decl(literalTypeWidening.ts, 116, 1))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 118, 21))
|
||||
>V : Symbol(V, Decl(literalTypeWidening.ts, 118, 38))
|
||||
>obj : Symbol(obj, Decl(literalTypeWidening.ts, 118, 42))
|
||||
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 118, 21))
|
||||
>V : Symbol(V, Decl(literalTypeWidening.ts, 118, 38))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 118, 21))
|
||||
|
||||
return Object.keys(obj) as K[]
|
||||
>Object.keys : Symbol(ObjectConstructor.keys, Decl(lib.d.ts, --, --))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>keys : Symbol(ObjectConstructor.keys, Decl(lib.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(literalTypeWidening.ts, 118, 42))
|
||||
>K : Symbol(K, Decl(literalTypeWidening.ts, 118, 21))
|
||||
}
|
||||
|
||||
type Obj = { code: LangCode }
|
||||
>Obj : Symbol(Obj, Decl(literalTypeWidening.ts, 120, 1))
|
||||
>code : Symbol(code, Decl(literalTypeWidening.ts, 122, 12))
|
||||
>LangCode : Symbol(LangCode, Decl(literalTypeWidening.ts, 124, 53))
|
||||
|
||||
const langCodeSet = Set('fr', 'en', 'es', 'it', 'nl')
|
||||
>langCodeSet : Symbol(langCodeSet, Decl(literalTypeWidening.ts, 124, 5))
|
||||
>Set : Symbol(Set, Decl(literalTypeWidening.ts, 108, 22))
|
||||
|
||||
export type LangCode = keyof typeof langCodeSet
|
||||
>LangCode : Symbol(LangCode, Decl(literalTypeWidening.ts, 124, 53))
|
||||
>langCodeSet : Symbol(langCodeSet, Decl(literalTypeWidening.ts, 124, 5))
|
||||
|
||||
export const langCodes = keys(langCodeSet)
|
||||
>langCodes : Symbol(langCodes, Decl(literalTypeWidening.ts, 126, 12))
|
||||
>keys : Symbol(keys, Decl(literalTypeWidening.ts, 116, 1))
|
||||
>langCodeSet : Symbol(langCodeSet, Decl(literalTypeWidening.ts, 124, 5))
|
||||
|
||||
const arr: Obj[] = langCodes.map(code => ({ code }))
|
||||
>arr : Symbol(arr, Decl(literalTypeWidening.ts, 128, 5))
|
||||
>Obj : Symbol(Obj, Decl(literalTypeWidening.ts, 120, 1))
|
||||
>langCodes.map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>langCodes : Symbol(langCodes, Decl(literalTypeWidening.ts, 126, 12))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>code : Symbol(code, Decl(literalTypeWidening.ts, 128, 33))
|
||||
>code : Symbol(code, Decl(literalTypeWidening.ts, 128, 43))
|
||||
|
||||
|
||||
@@ -219,6 +219,67 @@ function f5() {
|
||||
>c4 : "foo"
|
||||
}
|
||||
|
||||
declare function widening<T>(x: T): T;
|
||||
>widening : <T>(x: T) => T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
declare function nonWidening<T extends string | number | symbol>(x: T): T;
|
||||
>nonWidening : <T extends string | number | symbol>(x: T) => T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
function f6(cond: boolean) {
|
||||
>f6 : (cond: boolean) => void
|
||||
>cond : boolean
|
||||
|
||||
let x1 = widening('a');
|
||||
>x1 : string
|
||||
>widening('a') : "a"
|
||||
>widening : <T>(x: T) => T
|
||||
>'a' : "a"
|
||||
|
||||
let x2 = widening(10);
|
||||
>x2 : number
|
||||
>widening(10) : 10
|
||||
>widening : <T>(x: T) => T
|
||||
>10 : 10
|
||||
|
||||
let x3 = widening(cond ? 'a' : 10);
|
||||
>x3 : string | number
|
||||
>widening(cond ? 'a' : 10) : "a" | 10
|
||||
>widening : <T>(x: T) => T
|
||||
>cond ? 'a' : 10 : "a" | 10
|
||||
>cond : boolean
|
||||
>'a' : "a"
|
||||
>10 : 10
|
||||
|
||||
let y1 = nonWidening('a');
|
||||
>y1 : "a"
|
||||
>nonWidening('a') : "a"
|
||||
>nonWidening : <T extends string | number | symbol>(x: T) => T
|
||||
>'a' : "a"
|
||||
|
||||
let y2 = nonWidening(10);
|
||||
>y2 : 10
|
||||
>nonWidening(10) : 10
|
||||
>nonWidening : <T extends string | number | symbol>(x: T) => T
|
||||
>10 : 10
|
||||
|
||||
let y3 = nonWidening(cond ? 'a' : 10);
|
||||
>y3 : "a" | 10
|
||||
>nonWidening(cond ? 'a' : 10) : "a" | 10
|
||||
>nonWidening : <T extends string | number | symbol>(x: T) => T
|
||||
>cond ? 'a' : 10 : "a" | 10
|
||||
>cond : boolean
|
||||
>'a' : "a"
|
||||
>10 : 10
|
||||
}
|
||||
|
||||
// Repro from #10898
|
||||
|
||||
type FAILURE = "FAILURE";
|
||||
@@ -316,3 +377,97 @@ let x = onMouseOver();
|
||||
>onMouseOver() : TestEvent
|
||||
>onMouseOver : () => TestEvent
|
||||
|
||||
// Repro from #23649
|
||||
|
||||
export function Set<K extends string>(...keys: K[]): Record<K, true | undefined> {
|
||||
>Set : <K extends string>(...keys: K[]) => Record<K, true>
|
||||
>K : K
|
||||
>keys : K[]
|
||||
>K : K
|
||||
>Record : Record<K, T>
|
||||
>K : K
|
||||
>true : true
|
||||
|
||||
const result = {} as Record<K, true | undefined>
|
||||
>result : Record<K, true>
|
||||
>{} as Record<K, true | undefined> : Record<K, true>
|
||||
>{} : {}
|
||||
>Record : Record<K, T>
|
||||
>K : K
|
||||
>true : true
|
||||
|
||||
keys.forEach(key => result[key] = true)
|
||||
>keys.forEach(key => result[key] = true) : void
|
||||
>keys.forEach : (callbackfn: (value: K, index: number, array: K[]) => void, thisArg?: any) => void
|
||||
>keys : K[]
|
||||
>forEach : (callbackfn: (value: K, index: number, array: K[]) => void, thisArg?: any) => void
|
||||
>key => result[key] = true : (key: K) => boolean
|
||||
>key : K
|
||||
>result[key] = true : true
|
||||
>result[key] : Record<K, true>[K]
|
||||
>result : Record<K, true>
|
||||
>key : K
|
||||
>true : true
|
||||
|
||||
return result
|
||||
>result : Record<K, true>
|
||||
}
|
||||
|
||||
export function keys<K extends string, V>(obj: Record<K, V>): K[] {
|
||||
>keys : <K extends string, V>(obj: Record<K, V>) => K[]
|
||||
>K : K
|
||||
>V : V
|
||||
>obj : Record<K, V>
|
||||
>Record : Record<K, T>
|
||||
>K : K
|
||||
>V : V
|
||||
>K : K
|
||||
|
||||
return Object.keys(obj) as K[]
|
||||
>Object.keys(obj) as K[] : K[]
|
||||
>Object.keys(obj) : string[]
|
||||
>Object.keys : (o: {}) => string[]
|
||||
>Object : ObjectConstructor
|
||||
>keys : (o: {}) => string[]
|
||||
>obj : Record<K, V>
|
||||
>K : K
|
||||
}
|
||||
|
||||
type Obj = { code: LangCode }
|
||||
>Obj : Obj
|
||||
>code : "fr" | "en" | "es" | "it" | "nl"
|
||||
>LangCode : "fr" | "en" | "es" | "it" | "nl"
|
||||
|
||||
const langCodeSet = Set('fr', 'en', 'es', 'it', 'nl')
|
||||
>langCodeSet : Record<"fr" | "en" | "es" | "it" | "nl", true>
|
||||
>Set('fr', 'en', 'es', 'it', 'nl') : Record<"fr" | "en" | "es" | "it" | "nl", true>
|
||||
>Set : <K extends string>(...keys: K[]) => Record<K, true>
|
||||
>'fr' : "fr"
|
||||
>'en' : "en"
|
||||
>'es' : "es"
|
||||
>'it' : "it"
|
||||
>'nl' : "nl"
|
||||
|
||||
export type LangCode = keyof typeof langCodeSet
|
||||
>LangCode : "fr" | "en" | "es" | "it" | "nl"
|
||||
>langCodeSet : Record<"fr" | "en" | "es" | "it" | "nl", true>
|
||||
|
||||
export const langCodes = keys(langCodeSet)
|
||||
>langCodes : ("fr" | "en" | "es" | "it" | "nl")[]
|
||||
>keys(langCodeSet) : ("fr" | "en" | "es" | "it" | "nl")[]
|
||||
>keys : <K extends string, V>(obj: Record<K, V>) => K[]
|
||||
>langCodeSet : Record<"fr" | "en" | "es" | "it" | "nl", true>
|
||||
|
||||
const arr: Obj[] = langCodes.map(code => ({ code }))
|
||||
>arr : Obj[]
|
||||
>Obj : Obj
|
||||
>langCodes.map(code => ({ code })) : { code: "fr" | "en" | "es" | "it" | "nl"; }[]
|
||||
>langCodes.map : <U>(callbackfn: (value: "fr" | "en" | "es" | "it" | "nl", index: number, array: ("fr" | "en" | "es" | "it" | "nl")[]) => U, thisArg?: any) => U[]
|
||||
>langCodes : ("fr" | "en" | "es" | "it" | "nl")[]
|
||||
>map : <U>(callbackfn: (value: "fr" | "en" | "es" | "it" | "nl", index: number, array: ("fr" | "en" | "es" | "it" | "nl")[]) => U, thisArg?: any) => U[]
|
||||
>code => ({ code }) : (code: "fr" | "en" | "es" | "it" | "nl") => { code: "fr" | "en" | "es" | "it" | "nl"; }
|
||||
>code : "fr" | "en" | "es" | "it" | "nl"
|
||||
>({ code }) : { code: "fr" | "en" | "es" | "it" | "nl"; }
|
||||
>{ code } : { code: "fr" | "en" | "es" | "it" | "nl"; }
|
||||
>code : "fr" | "en" | "es" | "it" | "nl"
|
||||
|
||||
|
||||
@@ -555,7 +555,7 @@ class C2 {
|
||||
>bar : () => 1 | 0
|
||||
|
||||
return cond ? 0 : 1;
|
||||
>cond ? 0 : 1 : 1 | 0
|
||||
>cond ? 0 : 1 : 0 | 1
|
||||
>cond : boolean
|
||||
>0 : 0
|
||||
>1 : 1
|
||||
|
||||
@@ -107,7 +107,7 @@ function f5(x: number, y: 1 | 2) {
|
||||
>y : 1 | 2
|
||||
|
||||
x; // 0 | 1 | 2
|
||||
>x : 1 | 2 | 0
|
||||
>x : 0 | 1 | 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ function f6(x: number, y: 1 | 2) {
|
||||
>x : number
|
||||
|
||||
x; // 0 | 1 | 2
|
||||
>x : 1 | 2 | 0
|
||||
>x : 0 | 1 | 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ var i: I<string>;
|
||||
>I : I<T>
|
||||
|
||||
var y = new i(""); // y should be string
|
||||
>y : string
|
||||
>y : ""
|
||||
>new i("") : ""
|
||||
>i : I<string>
|
||||
>"" : ""
|
||||
|
||||
@@ -26,7 +26,7 @@ export function removeClass (node:HTMLElement, className:string) {
|
||||
>rightDelimiter : any
|
||||
|
||||
return leftDelimiter.length + rightDelimiter.length === 2 ? ' ' : '';
|
||||
>leftDelimiter.length + rightDelimiter.length === 2 ? ' ' : '' : " " | ""
|
||||
>leftDelimiter.length + rightDelimiter.length === 2 ? ' ' : '' : "" | " "
|
||||
>leftDelimiter.length + rightDelimiter.length === 2 : boolean
|
||||
>leftDelimiter.length + rightDelimiter.length : any
|
||||
>leftDelimiter.length : any
|
||||
|
||||
@@ -144,14 +144,14 @@ function f2<T, U>(x: T, y: U) {
|
||||
|
||||
var r2 = true ? '' : x;
|
||||
>r2 : string | T
|
||||
>true ? '' : x : T | ""
|
||||
>true ? '' : x : "" | T
|
||||
>true : true
|
||||
>'' : ""
|
||||
>x : T
|
||||
|
||||
var r2 = true ? x : '';
|
||||
>r2 : string | T
|
||||
>true ? x : '' : T | ""
|
||||
>true ? x : '' : "" | T
|
||||
>true : true
|
||||
>x : T
|
||||
>'' : ""
|
||||
|
||||
@@ -259,14 +259,14 @@ function f6<T extends String>(x: T) {
|
||||
|
||||
var r2 = true ? '' : x; // ok
|
||||
>r2 : string | T
|
||||
>true ? '' : x : T | ""
|
||||
>true ? '' : x : "" | T
|
||||
>true : true
|
||||
>'' : ""
|
||||
>x : T
|
||||
|
||||
var r2 = true ? x : ''; // ok
|
||||
>r2 : string | T
|
||||
>true ? x : '' : T | ""
|
||||
>true ? x : '' : "" | T
|
||||
>true : true
|
||||
>x : T
|
||||
>'' : ""
|
||||
|
||||
@@ -699,19 +699,19 @@ g(N["s"]);
|
||||
|
||||
// falsy expressions
|
||||
s || "";
|
||||
>s || "" : unique symbol | ""
|
||||
>s || "" : "" | unique symbol
|
||||
>s : unique symbol
|
||||
>"" : ""
|
||||
|
||||
N.s || "";
|
||||
>N.s || "" : unique symbol | ""
|
||||
>N.s || "" : "" | unique symbol
|
||||
>N.s : unique symbol
|
||||
>N : typeof N
|
||||
>s : unique symbol
|
||||
>"" : ""
|
||||
|
||||
N["s"] || "";
|
||||
>N["s"] || "" : unique symbol | ""
|
||||
>N["s"] || "" : "" | unique symbol
|
||||
>N["s"] : unique symbol
|
||||
>N : typeof N
|
||||
>"s" : "s"
|
||||
|
||||
@@ -699,19 +699,19 @@ g(N["s"]);
|
||||
|
||||
// falsy expressions
|
||||
s || "";
|
||||
>s || "" : unique symbol | ""
|
||||
>s || "" : "" | unique symbol
|
||||
>s : unique symbol
|
||||
>"" : ""
|
||||
|
||||
N.s || "";
|
||||
>N.s || "" : unique symbol | ""
|
||||
>N.s || "" : "" | unique symbol
|
||||
>N.s : unique symbol
|
||||
>N : typeof N
|
||||
>s : unique symbol
|
||||
>"" : ""
|
||||
|
||||
N["s"] || "";
|
||||
>N["s"] || "" : unique symbol | ""
|
||||
>N["s"] || "" : "" | unique symbol
|
||||
>N["s"] : unique symbol
|
||||
>N : typeof N
|
||||
>"s" : "s"
|
||||
|
||||
@@ -59,6 +59,18 @@ function f5() {
|
||||
let v4 = c4;
|
||||
}
|
||||
|
||||
declare function widening<T>(x: T): T;
|
||||
declare function nonWidening<T extends string | number | symbol>(x: T): T;
|
||||
|
||||
function f6(cond: boolean) {
|
||||
let x1 = widening('a');
|
||||
let x2 = widening(10);
|
||||
let x3 = widening(cond ? 'a' : 10);
|
||||
let y1 = nonWidening('a');
|
||||
let y2 = nonWidening(10);
|
||||
let y3 = nonWidening(cond ? 'a' : 10);
|
||||
}
|
||||
|
||||
// Repro from #10898
|
||||
|
||||
type FAILURE = "FAILURE";
|
||||
@@ -94,4 +106,24 @@ type TestEvent = "onmouseover" | "onmouseout";
|
||||
|
||||
function onMouseOver(): TestEvent { return "onmouseover"; }
|
||||
|
||||
let x = onMouseOver();
|
||||
let x = onMouseOver();
|
||||
|
||||
// Repro from #23649
|
||||
|
||||
export function Set<K extends string>(...keys: K[]): Record<K, true | undefined> {
|
||||
const result = {} as Record<K, true | undefined>
|
||||
keys.forEach(key => result[key] = true)
|
||||
return result
|
||||
}
|
||||
|
||||
export function keys<K extends string, V>(obj: Record<K, V>): K[] {
|
||||
return Object.keys(obj) as K[]
|
||||
}
|
||||
|
||||
type Obj = { code: LangCode }
|
||||
|
||||
const langCodeSet = Set('fr', 'en', 'es', 'it', 'nl')
|
||||
export type LangCode = keyof typeof langCodeSet
|
||||
export const langCodes = keys(langCodeSet)
|
||||
|
||||
const arr: Obj[] = langCodes.map(code => ({ code }))
|
||||
|
||||
Reference in New Issue
Block a user