Fix getTypeFacts for pattern template literal types (#41693)

* Normalize `${string}` to just string, fix getTypeFacts

* Add tests

* Accept new baselines
This commit is contained in:
Anders Hejlsberg
2020-11-26 06:55:01 -10:00
committed by GitHub
parent d616d8fc11
commit 411c6d04c6
6 changed files with 231 additions and 1 deletions
+5 -1
View File
@@ -13683,6 +13683,9 @@ namespace ts {
return getLiteralType(text);
}
newTexts.push(text);
if (every(newTexts, t => t === "") && every(newTypes, t => !!(t.flags & TypeFlags.String))) {
return stringType;
}
const id = `${getTypeListId(newTypes)}|${map(newTexts, t => t.length).join(",")}|${newTexts.join("")}`;
let type = templateLiteralTypes.get(id);
if (!type) {
@@ -21056,7 +21059,8 @@ namespace ts {
return TypeFacts.None;
}
if (flags & TypeFlags.Instantiable) {
return getTypeFacts(getBaseConstraintOfType(type) || unknownType);
return !isPatternLiteralType(type) ? getTypeFacts(getBaseConstraintOfType(type) || unknownType) :
strictNullChecks ? TypeFacts.NonEmptyStringStrictFacts : TypeFacts.NonEmptyStringFacts;
}
if (flags & TypeFlags.UnionOrIntersection) {
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
@@ -347,4 +347,30 @@ tests/cases/conformance/types/literal/templateLiteralTypesPatterns.ts(160,7): er
var bb: `${number}`;
var bb: `${number}` | '0';
// Normalize `${string}` to just string
type T2S<A extends string, B extends string> = `${A}${B}`;
type S10 = `${string}`; // string
type S11 = `${string}${string}${string}`; // string
type S12 = T2S<string, string>; // string
function ff1(x: `${string}-${string}`) {
let s1 = x && 42; // number
let s2 = x || 42; // `${string}-${string}`
}
// Repro from #41651
export type Id<TA, TId extends string = string> = `${TId}-${TId}`;
export class AA {}
export abstract class BB {
abstract get(id: Id<AA>): void;
update(id: Id<AA>): void {
this.get(id!);
}
}
@@ -174,10 +174,38 @@ let t3: `foo1` | '1foo' | 'foofoo' | `foo${string}` | 'foox' | 'xfoo' | `${numbe
var bb: `${number}`;
var bb: `${number}` | '0';
// Normalize `${string}` to just string
type T2S<A extends string, B extends string> = `${A}${B}`;
type S10 = `${string}`; // string
type S11 = `${string}${string}${string}`; // string
type S12 = T2S<string, string>; // string
function ff1(x: `${string}-${string}`) {
let s1 = x && 42; // number
let s2 = x || 42; // `${string}-${string}`
}
// Repro from #41651
export type Id<TA, TId extends string = string> = `${TId}-${TId}`;
export class AA {}
export abstract class BB {
abstract get(id: Id<AA>): void;
update(id: Id<AA>): void {
this.get(id!);
}
}
//// [templateLiteralTypesPatterns.js]
"use strict";
exports.__esModule = true;
exports.BB = exports.AA = void 0;
// ok
var a = "/bin";
// not ok
@@ -304,3 +332,22 @@ var t2; // `foo${string}` | '1foo' | 'xfoo'
var t3; // `foo${string}` | xfoo' | `${number}foo`
var bb;
var bb;
function ff1(x) {
var s1 = x && 42; // number
var s2 = x || 42; // `${string}-${string}`
}
var AA = /** @class */ (function () {
function AA() {
}
return AA;
}());
exports.AA = AA;
var BB = /** @class */ (function () {
function BB() {
}
BB.prototype.update = function (id) {
this.get(id);
};
return BB;
}());
exports.BB = BB;
@@ -418,3 +418,70 @@ var bb: `${number}`;
var bb: `${number}` | '0';
>bb : Symbol(bb, Decl(templateLiteralTypesPatterns.ts, 173, 3), Decl(templateLiteralTypesPatterns.ts, 174, 3))
// Normalize `${string}` to just string
type T2S<A extends string, B extends string> = `${A}${B}`;
>T2S : Symbol(T2S, Decl(templateLiteralTypesPatterns.ts, 174, 26))
>A : Symbol(A, Decl(templateLiteralTypesPatterns.ts, 178, 9))
>B : Symbol(B, Decl(templateLiteralTypesPatterns.ts, 178, 26))
>A : Symbol(A, Decl(templateLiteralTypesPatterns.ts, 178, 9))
>B : Symbol(B, Decl(templateLiteralTypesPatterns.ts, 178, 26))
type S10 = `${string}`; // string
>S10 : Symbol(S10, Decl(templateLiteralTypesPatterns.ts, 178, 58))
type S11 = `${string}${string}${string}`; // string
>S11 : Symbol(S11, Decl(templateLiteralTypesPatterns.ts, 180, 23))
type S12 = T2S<string, string>; // string
>S12 : Symbol(S12, Decl(templateLiteralTypesPatterns.ts, 181, 41))
>T2S : Symbol(T2S, Decl(templateLiteralTypesPatterns.ts, 174, 26))
function ff1(x: `${string}-${string}`) {
>ff1 : Symbol(ff1, Decl(templateLiteralTypesPatterns.ts, 182, 31))
>x : Symbol(x, Decl(templateLiteralTypesPatterns.ts, 184, 13))
let s1 = x && 42; // number
>s1 : Symbol(s1, Decl(templateLiteralTypesPatterns.ts, 185, 7))
>x : Symbol(x, Decl(templateLiteralTypesPatterns.ts, 184, 13))
let s2 = x || 42; // `${string}-${string}`
>s2 : Symbol(s2, Decl(templateLiteralTypesPatterns.ts, 186, 7))
>x : Symbol(x, Decl(templateLiteralTypesPatterns.ts, 184, 13))
}
// Repro from #41651
export type Id<TA, TId extends string = string> = `${TId}-${TId}`;
>Id : Symbol(Id, Decl(templateLiteralTypesPatterns.ts, 187, 1))
>TA : Symbol(TA, Decl(templateLiteralTypesPatterns.ts, 191, 15))
>TId : Symbol(TId, Decl(templateLiteralTypesPatterns.ts, 191, 18))
>TId : Symbol(TId, Decl(templateLiteralTypesPatterns.ts, 191, 18))
>TId : Symbol(TId, Decl(templateLiteralTypesPatterns.ts, 191, 18))
export class AA {}
>AA : Symbol(AA, Decl(templateLiteralTypesPatterns.ts, 191, 66))
export abstract class BB {
>BB : Symbol(BB, Decl(templateLiteralTypesPatterns.ts, 193, 18))
abstract get(id: Id<AA>): void;
>get : Symbol(BB.get, Decl(templateLiteralTypesPatterns.ts, 195, 26))
>id : Symbol(id, Decl(templateLiteralTypesPatterns.ts, 196, 17))
>Id : Symbol(Id, Decl(templateLiteralTypesPatterns.ts, 187, 1))
>AA : Symbol(AA, Decl(templateLiteralTypesPatterns.ts, 191, 66))
update(id: Id<AA>): void {
>update : Symbol(BB.update, Decl(templateLiteralTypesPatterns.ts, 196, 35))
>id : Symbol(id, Decl(templateLiteralTypesPatterns.ts, 197, 11))
>Id : Symbol(Id, Decl(templateLiteralTypesPatterns.ts, 187, 1))
>AA : Symbol(AA, Decl(templateLiteralTypesPatterns.ts, 191, 66))
this.get(id!);
>this.get : Symbol(BB.get, Decl(templateLiteralTypesPatterns.ts, 195, 26))
>this : Symbol(BB, Decl(templateLiteralTypesPatterns.ts, 193, 18))
>get : Symbol(BB.get, Decl(templateLiteralTypesPatterns.ts, 195, 26))
>id : Symbol(id, Decl(templateLiteralTypesPatterns.ts, 197, 11))
}
}
@@ -577,3 +577,63 @@ var bb: `${number}`;
var bb: `${number}` | '0';
>bb : `${number}`
// Normalize `${string}` to just string
type T2S<A extends string, B extends string> = `${A}${B}`;
>T2S : `${A}${B}`
type S10 = `${string}`; // string
>S10 : string
type S11 = `${string}${string}${string}`; // string
>S11 : string
type S12 = T2S<string, string>; // string
>S12 : string
function ff1(x: `${string}-${string}`) {
>ff1 : (x: `${string}-${string}`) => void
>x : `${string}-${string}`
let s1 = x && 42; // number
>s1 : number
>x && 42 : 42
>x : `${string}-${string}`
>42 : 42
let s2 = x || 42; // `${string}-${string}`
>s2 : `${string}-${string}`
>x || 42 : `${string}-${string}`
>x : `${string}-${string}`
>42 : 42
}
// Repro from #41651
export type Id<TA, TId extends string = string> = `${TId}-${TId}`;
>Id : `${TId}-${TId}`
export class AA {}
>AA : AA
export abstract class BB {
>BB : BB
abstract get(id: Id<AA>): void;
>get : (id: Id<AA>) => void
>id : `${string}-${string}`
update(id: Id<AA>): void {
>update : (id: Id<AA>) => void
>id : `${string}-${string}`
this.get(id!);
>this.get(id!) : void
>this.get : (id: `${string}-${string}`) => void
>this : this
>get : (id: `${string}-${string}`) => void
>id! : `${string}-${string}`
>id : `${string}-${string}`
}
}
@@ -174,3 +174,29 @@ let t3: `foo1` | '1foo' | 'foofoo' | `foo${string}` | 'foox' | 'xfoo' | `${numbe
var bb: `${number}`;
var bb: `${number}` | '0';
// Normalize `${string}` to just string
type T2S<A extends string, B extends string> = `${A}${B}`;
type S10 = `${string}`; // string
type S11 = `${string}${string}${string}`; // string
type S12 = T2S<string, string>; // string
function ff1(x: `${string}-${string}`) {
let s1 = x && 42; // number
let s2 = x || 42; // `${string}-${string}`
}
// Repro from #41651
export type Id<TA, TId extends string = string> = `${TId}-${TId}`;
export class AA {}
export abstract class BB {
abstract get(id: Id<AA>): void;
update(id: Id<AA>): void {
this.get(id!);
}
}