Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ahejlsberg committed Sep 29, 2021
1 parent 7f34792 commit e1907a2
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 53 deletions.
43 changes: 42 additions & 1 deletion tests/baselines/reference/templateLiteralTypes3.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ tests/cases/conformance/types/literal/templateLiteralTypes3.ts(71,5): error TS23
tests/cases/conformance/types/literal/templateLiteralTypes3.ts(72,5): error TS2322: Type '`*${string}*`' is not assignable to type '`*${number}*`'.
tests/cases/conformance/types/literal/templateLiteralTypes3.ts(74,5): error TS2322: Type '"*false*" | "*true*"' is not assignable to type '`*${number}*`'.
Type '"*false*"' is not assignable to type '`*${number}*`'.
tests/cases/conformance/types/literal/templateLiteralTypes3.ts(133,9): error TS2367: This condition will always return 'false' since the types '`foo-${string}`' and '`baz-${string}`' have no overlap.


==== tests/cases/conformance/types/literal/templateLiteralTypes3.ts (6 errors) ====
==== tests/cases/conformance/types/literal/templateLiteralTypes3.ts (7 errors) ====
// Inference from template literal type to template literal type

type Foo1<T> = T extends `*${infer U}*` ? U : never;
Expand Down Expand Up @@ -146,4 +147,44 @@ tests/cases/conformance/types/literal/templateLiteralTypes3.ts(74,5): error TS23
declare function chain<F extends keyof Schema>(field: F | `${F}.${F}`): void;

chain("a");

// Repro from #46125

function ff1<T extends string>(x: `foo-${string}`, y: `${string}-bar`, z: `baz-${string}`) {
if (x === y) {
x; // `foo-${string}`
}
if (x === z) { // Error
~~~~~~~
!!! error TS2367: This condition will always return 'false' since the types '`foo-${string}`' and '`baz-${string}`' have no overlap.
}
}

function ff2(x: string, y: `foo-${string}` | 'bar') {
if (x === y) {
x; // `foo-${string}` | 'bar'
}
}

function ff3(x: string, y: `foo-${string}`) {
if (x === 'foo-test') {
x; // 'foo-test'
}
if (y === 'foo-test') {
y; // 'foo-test'
}
}

// Repro from #46045

export type Action =
| { type: `${string}_REQUEST` }
| { type: `${string}_SUCCESS`, response: string };

export function reducer(action: Action) {
if (action.type === 'FOO_SUCCESS') {
action.type;
action.response;
}
}

126 changes: 74 additions & 52 deletions tests/baselines/reference/templateLiteralTypes3.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,51 @@ type Schema = { a: { b: { c: number } } };
declare function chain<F extends keyof Schema>(field: F | `${F}.${F}`): void;

chain("a");

// Repro from #46125

function ff1<T extends string>(x: `foo-${string}`, y: `${string}-bar`, z: `baz-${string}`) {
if (x === y) {
x; // `foo-${string}`
}
if (x === z) { // Error
}
}

function ff2(x: string, y: `foo-${string}` | 'bar') {
if (x === y) {
x; // `foo-${string}` | 'bar'
}
}

function ff3(x: string, y: `foo-${string}`) {
if (x === 'foo-test') {
x; // 'foo-test'
}
if (y === 'foo-test') {
y; // 'foo-test'
}
}

// Repro from #46045

export type Action =
| { type: `${string}_REQUEST` }
| { type: `${string}_SUCCESS`, response: string };

export function reducer(action: Action) {
if (action.type === 'FOO_SUCCESS') {
action.type;
action.response;
}
}


//// [templateLiteralTypes3.js]
"use strict";
// Inference from template literal type to template literal type
exports.__esModule = true;
exports.reducer = void 0;
function f1(s, n, b, t) {
var x1 = foo1('hello'); // Error
var x2 = foo1('*hello*');
Expand Down Expand Up @@ -177,59 +217,41 @@ var templated1 = value1 + " abc";
var value2 = "abc";
var templated2 = value2 + " abc";
chain("a");
// Repro from #46125
function ff1(x, y, z) {
if (x === y) {
x; // `foo-${string}`
}
if (x === z) { // Error
}
}
function ff2(x, y) {
if (x === y) {
x; // `foo-${string}` | 'bar'
}
}
function ff3(x, y) {
if (x === 'foo-test') {
x; // 'foo-test'
}
if (y === 'foo-test') {
y; // 'foo-test'
}
}
function reducer(action) {
if (action.type === 'FOO_SUCCESS') {
action.type;
action.response;
}
}
exports.reducer = reducer;


//// [templateLiteralTypes3.d.ts]
declare type Foo1<T> = T extends `*${infer U}*` ? U : never;
declare type T01 = Foo1<'hello'>;
declare type T02 = Foo1<'*hello*'>;
declare type T03 = Foo1<'**hello**'>;
declare type T04 = Foo1<`*${string}*`>;
declare type T05 = Foo1<`*${number}*`>;
declare type T06 = Foo1<`*${bigint}*`>;
declare type T07 = Foo1<`*${any}*`>;
declare type T08 = Foo1<`**${string}**`>;
declare type T09 = Foo1<`**${string}**${string}**`>;
declare type T10 = Foo1<`**${'a' | 'b' | 'c'}**`>;
declare type T11 = Foo1<`**${boolean}**${boolean}**`>;
declare function foo1<V extends string>(arg: `*${V}*`): V;
declare function f1<T extends string>(s: string, n: number, b: boolean, t: T): void;
declare type Parts<T> = T extends '' ? [] : T extends `${infer Head}${infer Tail}` ? [Head, ...Parts<Tail>] : never;
declare type T20 = Parts<`abc`>;
declare type T21 = Parts<`*${string}*`>;
declare type T22 = Parts<`*${number}*`>;
declare type T23 = Parts<`*${number}*${string}*${bigint}*`>;
declare function f2(): void;
declare function f3<T extends string>(s: string, n: number, b: boolean, t: T): void;
declare function f4<T extends number>(s: string, n: number, b: boolean, t: T): void;
declare type A<T> = T extends `${infer U}.${infer V}` ? U | V : never;
declare type B = A<`test.1024`>;
declare type C = A<`test.${number}`>;
declare type D<T> = T extends `${infer U}.${number}` ? U : never;
declare type E = D<`test.1024`>;
declare type F = D<`test.${number}`>;
declare type G<T> = T extends `${infer U}.${infer V}` ? U | V : never;
declare type H = G<`test.hoge`>;
declare type I = G<`test.${string}`>;
declare type J<T> = T extends `${infer U}.${string}` ? U : never;
declare type K = J<`test.hoge`>;
declare type L = J<`test.${string}`>;
declare type Templated = `${string} ${string}`;
declare const value1: string;
declare const templated1: Templated;
declare const value2 = "abc";
declare const templated2: Templated;
declare type Prefixes = "foo" | "bar";
declare type AllPrefixData = "foo:baz" | "bar:baz";
declare type PrefixData<P extends Prefixes> = `${P}:baz`;
interface ITest<P extends Prefixes, E extends AllPrefixData = PrefixData<P>> {
blah: string;
}
declare type Schema = {
a: {
b: {
c: number;
};
};
export declare type Action = {
type: `${string}_REQUEST`;
} | {
type: `${string}_SUCCESS`;
response: string;
};
declare function chain<F extends keyof Schema>(field: F | `${F}.${F}`): void;
export declare function reducer(action: Action): void;
89 changes: 89 additions & 0 deletions tests/baselines/reference/templateLiteralTypes3.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -405,3 +405,92 @@ declare function chain<F extends keyof Schema>(field: F | `${F}.${F}`): void;
chain("a");
>chain : Symbol(chain, Decl(templateLiteralTypes3.ts, 120, 42))

// Repro from #46125

function ff1<T extends string>(x: `foo-${string}`, y: `${string}-bar`, z: `baz-${string}`) {
>ff1 : Symbol(ff1, Decl(templateLiteralTypes3.ts, 124, 11))
>T : Symbol(T, Decl(templateLiteralTypes3.ts, 128, 13))
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 128, 31))
>y : Symbol(y, Decl(templateLiteralTypes3.ts, 128, 50))
>z : Symbol(z, Decl(templateLiteralTypes3.ts, 128, 70))

if (x === y) {
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 128, 31))
>y : Symbol(y, Decl(templateLiteralTypes3.ts, 128, 50))

x; // `foo-${string}`
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 128, 31))
}
if (x === z) { // Error
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 128, 31))
>z : Symbol(z, Decl(templateLiteralTypes3.ts, 128, 70))
}
}

function ff2(x: string, y: `foo-${string}` | 'bar') {
>ff2 : Symbol(ff2, Decl(templateLiteralTypes3.ts, 134, 1))
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 136, 13))
>y : Symbol(y, Decl(templateLiteralTypes3.ts, 136, 23))

if (x === y) {
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 136, 13))
>y : Symbol(y, Decl(templateLiteralTypes3.ts, 136, 23))

x; // `foo-${string}` | 'bar'
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 136, 13))
}
}

function ff3(x: string, y: `foo-${string}`) {
>ff3 : Symbol(ff3, Decl(templateLiteralTypes3.ts, 140, 1))
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 142, 13))
>y : Symbol(y, Decl(templateLiteralTypes3.ts, 142, 23))

if (x === 'foo-test') {
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 142, 13))

x; // 'foo-test'
>x : Symbol(x, Decl(templateLiteralTypes3.ts, 142, 13))
}
if (y === 'foo-test') {
>y : Symbol(y, Decl(templateLiteralTypes3.ts, 142, 23))

y; // 'foo-test'
>y : Symbol(y, Decl(templateLiteralTypes3.ts, 142, 23))
}
}

// Repro from #46045

export type Action =
>Action : Symbol(Action, Decl(templateLiteralTypes3.ts, 149, 1))

| { type: `${string}_REQUEST` }
>type : Symbol(type, Decl(templateLiteralTypes3.ts, 154, 7))

| { type: `${string}_SUCCESS`, response: string };
>type : Symbol(type, Decl(templateLiteralTypes3.ts, 155, 7))
>response : Symbol(response, Decl(templateLiteralTypes3.ts, 155, 34))

export function reducer(action: Action) {
>reducer : Symbol(reducer, Decl(templateLiteralTypes3.ts, 155, 54))
>action : Symbol(action, Decl(templateLiteralTypes3.ts, 157, 24))
>Action : Symbol(Action, Decl(templateLiteralTypes3.ts, 149, 1))

if (action.type === 'FOO_SUCCESS') {
>action.type : Symbol(type, Decl(templateLiteralTypes3.ts, 154, 7), Decl(templateLiteralTypes3.ts, 155, 7))
>action : Symbol(action, Decl(templateLiteralTypes3.ts, 157, 24))
>type : Symbol(type, Decl(templateLiteralTypes3.ts, 154, 7), Decl(templateLiteralTypes3.ts, 155, 7))

action.type;
>action.type : Symbol(type, Decl(templateLiteralTypes3.ts, 155, 7))
>action : Symbol(action, Decl(templateLiteralTypes3.ts, 157, 24))
>type : Symbol(type, Decl(templateLiteralTypes3.ts, 155, 7))

action.response;
>action.response : Symbol(response, Decl(templateLiteralTypes3.ts, 155, 34))
>action : Symbol(action, Decl(templateLiteralTypes3.ts, 157, 24))
>response : Symbol(response, Decl(templateLiteralTypes3.ts, 155, 34))
}
}

96 changes: 96 additions & 0 deletions tests/baselines/reference/templateLiteralTypes3.types
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,99 @@ chain("a");
>chain : <F extends "a">(field: F | `${F}.${F}`) => void
>"a" : "a"

// Repro from #46125

function ff1<T extends string>(x: `foo-${string}`, y: `${string}-bar`, z: `baz-${string}`) {
>ff1 : <T extends string>(x: `foo-${string}`, y: `${string}-bar`, z: `baz-${string}`) => void
>x : `foo-${string}`
>y : `${string}-bar`
>z : `baz-${string}`

if (x === y) {
>x === y : boolean
>x : `foo-${string}`
>y : `${string}-bar`

x; // `foo-${string}`
>x : `foo-${string}`
}
if (x === z) { // Error
>x === z : boolean
>x : `foo-${string}`
>z : `baz-${string}`
}
}

function ff2(x: string, y: `foo-${string}` | 'bar') {
>ff2 : (x: string, y: `foo-${string}` | 'bar') => void
>x : string
>y : "bar" | `foo-${string}`

if (x === y) {
>x === y : boolean
>x : string
>y : "bar" | `foo-${string}`

x; // `foo-${string}` | 'bar'
>x : "bar" | `foo-${string}`
}
}

function ff3(x: string, y: `foo-${string}`) {
>ff3 : (x: string, y: `foo-${string}`) => void
>x : string
>y : `foo-${string}`

if (x === 'foo-test') {
>x === 'foo-test' : boolean
>x : string
>'foo-test' : "foo-test"

x; // 'foo-test'
>x : "foo-test"
}
if (y === 'foo-test') {
>y === 'foo-test' : boolean
>y : `foo-${string}`
>'foo-test' : "foo-test"

y; // 'foo-test'
>y : "foo-test"
}
}

// Repro from #46045

export type Action =
>Action : Action

| { type: `${string}_REQUEST` }
>type : `${string}_REQUEST`

| { type: `${string}_SUCCESS`, response: string };
>type : `${string}_SUCCESS`
>response : string

export function reducer(action: Action) {
>reducer : (action: Action) => void
>action : Action

if (action.type === 'FOO_SUCCESS') {
>action.type === 'FOO_SUCCESS' : boolean
>action.type : `${string}_REQUEST` | `${string}_SUCCESS`
>action : Action
>type : `${string}_REQUEST` | `${string}_SUCCESS`
>'FOO_SUCCESS' : "FOO_SUCCESS"

action.type;
>action.type : "FOO_SUCCESS"
>action : { type: `${string}_SUCCESS`; response: string; }
>type : "FOO_SUCCESS"

action.response;
>action.response : string
>action : { type: `${string}_SUCCESS`; response: string; }
>response : string
}
}

Loading

0 comments on commit e1907a2

Please sign in to comment.