Merge pull request #29082 from Microsoft/widenIntersectionTypes

Properly widen intersection types
This commit is contained in:
Anders Hejlsberg 2018-12-18 12:53:33 -08:00 committed by GitHub
commit 8ac18be108
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 0 deletions

View File

@ -13597,6 +13597,9 @@ namespace ts {
// union includes empty object types (e.g. reducing {} | string to just {}).
return getUnionType(widenedTypes, some(widenedTypes, isEmptyObjectType) ? UnionReduction.Subtype : UnionReduction.Literal);
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(sameMap((<IntersectionType>type).types, getWidenedType));
}
if (isArrayType(type) || isTupleType(type)) {
return createTypeReference((<TypeReference>type).target, sameMap((<TypeReference>type).typeArguments, getWidenedType));
}

View File

@ -128,11 +128,38 @@ export type LangCode = keyof typeof langCodeSet
export const langCodes = keys(langCodeSet)
const arr: Obj[] = langCodes.map(code => ({ code }))
// Repro from #29081
function test<T extends { a: string, b: string }>(obj: T): T {
let { a, ...rest } = obj;
return { a: 'hello', ...rest } as T;
}
//// [literalTypeWidening.js]
"use strict";
// Widening vs. non-widening literal types
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
};
exports.__esModule = true;
function f1() {
var c1 = "hello"; // Widening type "hello"
@ -233,3 +260,8 @@ 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 }); });
// Repro from #29081
function test(obj) {
var a = obj.a, rest = __rest(obj, ["a"]);
return __assign({ a: 'hello' }, rest);
}

View File

@ -400,3 +400,25 @@ const arr: Obj[] = langCodes.map(code => ({ code }))
>code : Symbol(code, Decl(literalTypeWidening.ts, 128, 33))
>code : Symbol(code, Decl(literalTypeWidening.ts, 128, 43))
// Repro from #29081
function test<T extends { a: string, b: string }>(obj: T): T {
>test : Symbol(test, Decl(literalTypeWidening.ts, 128, 52))
>T : Symbol(T, Decl(literalTypeWidening.ts, 132, 14))
>a : Symbol(a, Decl(literalTypeWidening.ts, 132, 25))
>b : Symbol(b, Decl(literalTypeWidening.ts, 132, 36))
>obj : Symbol(obj, Decl(literalTypeWidening.ts, 132, 50))
>T : Symbol(T, Decl(literalTypeWidening.ts, 132, 14))
>T : Symbol(T, Decl(literalTypeWidening.ts, 132, 14))
let { a, ...rest } = obj;
>a : Symbol(a, Decl(literalTypeWidening.ts, 133, 9))
>rest : Symbol(rest, Decl(literalTypeWidening.ts, 133, 12))
>obj : Symbol(obj, Decl(literalTypeWidening.ts, 132, 50))
return { a: 'hello', ...rest } as T;
>a : Symbol(a, Decl(literalTypeWidening.ts, 134, 12))
>rest : Symbol(rest, Decl(literalTypeWidening.ts, 133, 12))
>T : Symbol(T, Decl(literalTypeWidening.ts, 132, 14))
}

View File

@ -433,3 +433,24 @@ const arr: Obj[] = langCodes.map(code => ({ code }))
>{ code } : { code: "fr" | "en" | "es" | "it" | "nl"; }
>code : "fr" | "en" | "es" | "it" | "nl"
// Repro from #29081
function test<T extends { a: string, b: string }>(obj: T): T {
>test : <T extends { a: string; b: string; }>(obj: T) => T
>a : string
>b : string
>obj : T
let { a, ...rest } = obj;
>a : string
>rest : Pick<T, Exclude<keyof T, "a">>
>obj : T
return { a: 'hello', ...rest } as T;
>{ a: 'hello', ...rest } as T : T
>{ a: 'hello', ...rest } : { a: string; } & Pick<T, Exclude<keyof T, "a">>
>a : string
>'hello' : "hello"
>rest : Pick<T, Exclude<keyof T, "a">>
}

View File

@ -127,3 +127,10 @@ export type LangCode = keyof typeof langCodeSet
export const langCodes = keys(langCodeSet)
const arr: Obj[] = langCodes.map(code => ({ code }))
// Repro from #29081
function test<T extends { a: string, b: string }>(obj: T): T {
let { a, ...rest } = obj;
return { a: 'hello', ...rest } as T;
}