mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Properly reduce intersections to never in identity relation (#48111)
* Exclude types that may simplify to other forms * Add regression test
This commit is contained in:
parent
04238e6f52
commit
0271738047
@ -18104,7 +18104,8 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (!((source.flags | target.flags) & (TypeFlags.UnionOrIntersection | TypeFlags.IndexedAccess | TypeFlags.Conditional | TypeFlags.Substitution))) {
|
||||
// We have excluded types that may simplify to other forms, so types must have identical flags
|
||||
if (source.flags !== target.flags) return false;
|
||||
if (source.flags & TypeFlags.Singleton) return true;
|
||||
}
|
||||
|
||||
42
tests/baselines/reference/identityRelationNeverTypes.js
Normal file
42
tests/baselines/reference/identityRelationNeverTypes.js
Normal file
@ -0,0 +1,42 @@
|
||||
//// [identityRelationNeverTypes.ts]
|
||||
// Repro from #47996
|
||||
|
||||
type Equals<A, B> = (<T>() => T extends B ? 1 : 0) extends (<T>() => T extends A ? 1 : 0) ? true : false;
|
||||
|
||||
declare class State<TContext> {
|
||||
_context: TContext;
|
||||
_value: string;
|
||||
matches<TSV extends string>(stateValue: TSV): this is State<TContext> & { value: TSV };
|
||||
}
|
||||
|
||||
function f1(state: State<{ foo: number }>) {
|
||||
if (state.matches('a') && state.matches('a.b')) {
|
||||
state; // never
|
||||
type T1 = Equals<typeof state, never>; // true
|
||||
type T2 = Equals<never, never>; // true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [identityRelationNeverTypes.js]
|
||||
"use strict";
|
||||
// Repro from #47996
|
||||
function f1(state) {
|
||||
if (state.matches('a') && state.matches('a.b')) {
|
||||
state; // never
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [identityRelationNeverTypes.d.ts]
|
||||
declare type Equals<A, B> = (<T>() => T extends B ? 1 : 0) extends (<T>() => T extends A ? 1 : 0) ? true : false;
|
||||
declare class State<TContext> {
|
||||
_context: TContext;
|
||||
_value: string;
|
||||
matches<TSV extends string>(stateValue: TSV): this is State<TContext> & {
|
||||
value: TSV;
|
||||
};
|
||||
}
|
||||
declare function f1(state: State<{
|
||||
foo: number;
|
||||
}>): void;
|
||||
64
tests/baselines/reference/identityRelationNeverTypes.symbols
Normal file
64
tests/baselines/reference/identityRelationNeverTypes.symbols
Normal file
@ -0,0 +1,64 @@
|
||||
=== tests/cases/compiler/identityRelationNeverTypes.ts ===
|
||||
// Repro from #47996
|
||||
|
||||
type Equals<A, B> = (<T>() => T extends B ? 1 : 0) extends (<T>() => T extends A ? 1 : 0) ? true : false;
|
||||
>Equals : Symbol(Equals, Decl(identityRelationNeverTypes.ts, 0, 0))
|
||||
>A : Symbol(A, Decl(identityRelationNeverTypes.ts, 2, 12))
|
||||
>B : Symbol(B, Decl(identityRelationNeverTypes.ts, 2, 14))
|
||||
>T : Symbol(T, Decl(identityRelationNeverTypes.ts, 2, 22))
|
||||
>T : Symbol(T, Decl(identityRelationNeverTypes.ts, 2, 22))
|
||||
>B : Symbol(B, Decl(identityRelationNeverTypes.ts, 2, 14))
|
||||
>T : Symbol(T, Decl(identityRelationNeverTypes.ts, 2, 61))
|
||||
>T : Symbol(T, Decl(identityRelationNeverTypes.ts, 2, 61))
|
||||
>A : Symbol(A, Decl(identityRelationNeverTypes.ts, 2, 12))
|
||||
|
||||
declare class State<TContext> {
|
||||
>State : Symbol(State, Decl(identityRelationNeverTypes.ts, 2, 105))
|
||||
>TContext : Symbol(TContext, Decl(identityRelationNeverTypes.ts, 4, 20))
|
||||
|
||||
_context: TContext;
|
||||
>_context : Symbol(State._context, Decl(identityRelationNeverTypes.ts, 4, 31))
|
||||
>TContext : Symbol(TContext, Decl(identityRelationNeverTypes.ts, 4, 20))
|
||||
|
||||
_value: string;
|
||||
>_value : Symbol(State._value, Decl(identityRelationNeverTypes.ts, 5, 23))
|
||||
|
||||
matches<TSV extends string>(stateValue: TSV): this is State<TContext> & { value: TSV };
|
||||
>matches : Symbol(State.matches, Decl(identityRelationNeverTypes.ts, 6, 19))
|
||||
>TSV : Symbol(TSV, Decl(identityRelationNeverTypes.ts, 7, 12))
|
||||
>stateValue : Symbol(stateValue, Decl(identityRelationNeverTypes.ts, 7, 32))
|
||||
>TSV : Symbol(TSV, Decl(identityRelationNeverTypes.ts, 7, 12))
|
||||
>State : Symbol(State, Decl(identityRelationNeverTypes.ts, 2, 105))
|
||||
>TContext : Symbol(TContext, Decl(identityRelationNeverTypes.ts, 4, 20))
|
||||
>value : Symbol(value, Decl(identityRelationNeverTypes.ts, 7, 77))
|
||||
>TSV : Symbol(TSV, Decl(identityRelationNeverTypes.ts, 7, 12))
|
||||
}
|
||||
|
||||
function f1(state: State<{ foo: number }>) {
|
||||
>f1 : Symbol(f1, Decl(identityRelationNeverTypes.ts, 8, 1))
|
||||
>state : Symbol(state, Decl(identityRelationNeverTypes.ts, 10, 12))
|
||||
>State : Symbol(State, Decl(identityRelationNeverTypes.ts, 2, 105))
|
||||
>foo : Symbol(foo, Decl(identityRelationNeverTypes.ts, 10, 26))
|
||||
|
||||
if (state.matches('a') && state.matches('a.b')) {
|
||||
>state.matches : Symbol(State.matches, Decl(identityRelationNeverTypes.ts, 6, 19))
|
||||
>state : Symbol(state, Decl(identityRelationNeverTypes.ts, 10, 12))
|
||||
>matches : Symbol(State.matches, Decl(identityRelationNeverTypes.ts, 6, 19))
|
||||
>state.matches : Symbol(State.matches, Decl(identityRelationNeverTypes.ts, 6, 19))
|
||||
>state : Symbol(state, Decl(identityRelationNeverTypes.ts, 10, 12))
|
||||
>matches : Symbol(State.matches, Decl(identityRelationNeverTypes.ts, 6, 19))
|
||||
|
||||
state; // never
|
||||
>state : Symbol(state, Decl(identityRelationNeverTypes.ts, 10, 12))
|
||||
|
||||
type T1 = Equals<typeof state, never>; // true
|
||||
>T1 : Symbol(T1, Decl(identityRelationNeverTypes.ts, 12, 14))
|
||||
>Equals : Symbol(Equals, Decl(identityRelationNeverTypes.ts, 0, 0))
|
||||
>state : Symbol(state, Decl(identityRelationNeverTypes.ts, 10, 12))
|
||||
|
||||
type T2 = Equals<never, never>; // true
|
||||
>T2 : Symbol(T2, Decl(identityRelationNeverTypes.ts, 13, 46))
|
||||
>Equals : Symbol(Equals, Decl(identityRelationNeverTypes.ts, 0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
53
tests/baselines/reference/identityRelationNeverTypes.types
Normal file
53
tests/baselines/reference/identityRelationNeverTypes.types
Normal file
@ -0,0 +1,53 @@
|
||||
=== tests/cases/compiler/identityRelationNeverTypes.ts ===
|
||||
// Repro from #47996
|
||||
|
||||
type Equals<A, B> = (<T>() => T extends B ? 1 : 0) extends (<T>() => T extends A ? 1 : 0) ? true : false;
|
||||
>Equals : Equals<A, B>
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
declare class State<TContext> {
|
||||
>State : State<TContext>
|
||||
|
||||
_context: TContext;
|
||||
>_context : TContext
|
||||
|
||||
_value: string;
|
||||
>_value : string
|
||||
|
||||
matches<TSV extends string>(stateValue: TSV): this is State<TContext> & { value: TSV };
|
||||
>matches : <TSV extends string>(stateValue: TSV) => this is State<TContext> & { value: TSV; }
|
||||
>stateValue : TSV
|
||||
>value : TSV
|
||||
}
|
||||
|
||||
function f1(state: State<{ foo: number }>) {
|
||||
>f1 : (state: State<{ foo: number;}>) => void
|
||||
>state : State<{ foo: number; }>
|
||||
>foo : number
|
||||
|
||||
if (state.matches('a') && state.matches('a.b')) {
|
||||
>state.matches('a') && state.matches('a.b') : boolean
|
||||
>state.matches('a') : boolean
|
||||
>state.matches : <TSV extends string>(stateValue: TSV) => this is State<{ foo: number; }> & { value: TSV; }
|
||||
>state : State<{ foo: number; }>
|
||||
>matches : <TSV extends string>(stateValue: TSV) => this is State<{ foo: number; }> & { value: TSV; }
|
||||
>'a' : "a"
|
||||
>state.matches('a.b') : boolean
|
||||
>state.matches : <TSV extends string>(stateValue: TSV) => this is State<{ foo: number; }> & { value: TSV; }
|
||||
>state : State<{ foo: number; }> & { value: "a"; }
|
||||
>matches : <TSV extends string>(stateValue: TSV) => this is State<{ foo: number; }> & { value: TSV; }
|
||||
>'a.b' : "a.b"
|
||||
|
||||
state; // never
|
||||
>state : never
|
||||
|
||||
type T1 = Equals<typeof state, never>; // true
|
||||
>T1 : true
|
||||
>state : never
|
||||
|
||||
type T2 = Equals<never, never>; // true
|
||||
>T2 : true
|
||||
}
|
||||
}
|
||||
|
||||
20
tests/cases/compiler/identityRelationNeverTypes.ts
Normal file
20
tests/cases/compiler/identityRelationNeverTypes.ts
Normal file
@ -0,0 +1,20 @@
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
// Repro from #47996
|
||||
|
||||
type Equals<A, B> = (<T>() => T extends B ? 1 : 0) extends (<T>() => T extends A ? 1 : 0) ? true : false;
|
||||
|
||||
declare class State<TContext> {
|
||||
_context: TContext;
|
||||
_value: string;
|
||||
matches<TSV extends string>(stateValue: TSV): this is State<TContext> & { value: TSV };
|
||||
}
|
||||
|
||||
function f1(state: State<{ foo: number }>) {
|
||||
if (state.matches('a') && state.matches('a.b')) {
|
||||
state; // never
|
||||
type T1 = Equals<typeof state, never>; // true
|
||||
type T2 = Equals<never, never>; // true
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user