Skip to content

Commit

Permalink
Consistently check assignability to template literal placeholders (#5…
Browse files Browse the repository at this point in the history
  • Loading branch information
ahejlsberg authored Nov 29, 2023
1 parent e551325 commit 68b9b07
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25017,12 +25017,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean {
if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) {
return true;
}
if (target.flags & TypeFlags.Intersection) {
return every((target as IntersectionType).types, t => t === emptyTypeLiteralType || isValidTypeForTemplateLiteralPlaceholder(source, t));
}
if (target.flags & TypeFlags.String || isTypeAssignableTo(source, target)) {
return true;
}
if (source.flags & TypeFlags.StringLiteral) {
const value = (source as StringLiteralType).value;
return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) ||
Expand All @@ -25035,7 +25035,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const texts = (source as TemplateLiteralType).texts;
return texts.length === 2 && texts[0] === "" && texts[1] === "" && isTypeAssignableTo((source as TemplateLiteralType).types[0], target);
}
return isTypeAssignableTo(source, target);
return false;
}

function inferTypesFromTemplateLiteralType(source: Type, target: TemplateLiteralType): Type[] | undefined {
Expand Down
8 changes: 8 additions & 0 deletions tests/baselines/reference/templateLiteralTypes3.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -221,4 +221,12 @@ templateLiteralTypes3.ts(141,9): error TS2367: This comparison appears to be uni
// Repro from #52685

type Boom = 'abc' | 'def' | `a${string}` | Lowercase<string>;

// Repro from #56582

function a<T extends {id: string}>() {
let x: keyof T & string | `-${keyof T & string}`;
x = "id";
x = "-id";
}

17 changes: 17 additions & 0 deletions tests/baselines/reference/templateLiteralTypes3.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,14 @@ function ft1<T extends string>(t: T, u: Uppercase<T>, u1: Uppercase<`1.${T}.3`>,
// Repro from #52685

type Boom = 'abc' | 'def' | `a${string}` | Lowercase<string>;

// Repro from #56582

function a<T extends {id: string}>() {
let x: keyof T & string | `-${keyof T & string}`;
x = "id";
x = "-id";
}


//// [templateLiteralTypes3.js]
Expand Down Expand Up @@ -291,6 +299,12 @@ function ft1(t, u, u1, u2) {
spread("1.".concat(u, ".3"), "1.".concat(u, ".4"));
spread(u1, u2);
}
// Repro from #56582
function a() {
var x;
x = "id";
x = "-id";
}


//// [templateLiteralTypes3.d.ts]
Expand Down Expand Up @@ -363,3 +377,6 @@ declare function noSpread<P extends DotString>(args: P[]): P;
declare function spread<P extends DotString>(...args: P[]): P;
declare function ft1<T extends string>(t: T, u: Uppercase<T>, u1: Uppercase<`1.${T}.3`>, u2: Uppercase<`1.${T}.4`>): void;
type Boom = 'abc' | 'def' | `a${string}` | Lowercase<string>;
declare function a<T extends {
id: string;
}>(): void;
19 changes: 19 additions & 0 deletions tests/baselines/reference/templateLiteralTypes3.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -588,3 +588,22 @@ type Boom = 'abc' | 'def' | `a${string}` | Lowercase<string>;
>Boom : Symbol(Boom, Decl(templateLiteralTypes3.ts, 189, 1))
>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))

// Repro from #56582

function a<T extends {id: string}>() {
>a : Symbol(a, Decl(templateLiteralTypes3.ts, 193, 61))
>T : Symbol(T, Decl(templateLiteralTypes3.ts, 197, 11))
>id : Symbol(id, Decl(templateLiteralTypes3.ts, 197, 22))

let x: keyof T & string | `-${keyof T & string}`;
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 198, 7))
>T : Symbol(T, Decl(templateLiteralTypes3.ts, 197, 11))
>T : Symbol(T, Decl(templateLiteralTypes3.ts, 197, 11))

x = "id";
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 198, 7))

x = "-id";
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 198, 7))
}

20 changes: 20 additions & 0 deletions tests/baselines/reference/templateLiteralTypes3.types
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,23 @@ function ft1<T extends string>(t: T, u: Uppercase<T>, u1: Uppercase<`1.${T}.3`>,
type Boom = 'abc' | 'def' | `a${string}` | Lowercase<string>;
>Boom : `a${string}` | Lowercase<string> | "def"

// Repro from #56582

function a<T extends {id: string}>() {
>a : <T extends { id: string; }>() => void
>id : string

let x: keyof T & string | `-${keyof T & string}`;
>x : (keyof T & string) | `-${keyof T & string}`

x = "id";
>x = "id" : "id"
>x : (keyof T & string) | `-${keyof T & string}`
>"id" : "id"

x = "-id";
>x = "-id" : "-id"
>x : (keyof T & string) | `-${keyof T & string}`
>"-id" : "-id"
}

Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,11 @@ function ft1<T extends string>(t: T, u: Uppercase<T>, u1: Uppercase<`1.${T}.3`>,
// Repro from #52685

type Boom = 'abc' | 'def' | `a${string}` | Lowercase<string>;

// Repro from #56582

function a<T extends {id: string}>() {
let x: keyof T & string | `-${keyof T & string}`;
x = "id";
x = "-id";
}

0 comments on commit 68b9b07

Please sign in to comment.