Properly propagate silentNeverType in intersections (#45073)

* Properly propagate silentNeverType in intersections

* Add regression test
This commit is contained in:
Anders Hejlsberg 2021-07-16 11:20:04 -07:00 committed by GitHub
parent d0efe9065e
commit 193b7494d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 245 additions and 2 deletions

View File

@ -14246,8 +14246,10 @@ namespace ts {
// a symbol-like type and a type known to be non-symbol-like, or
// a void-like type and a type known to be non-void-like, or
// a non-primitive type and a type known to be primitive.
if (includes & TypeFlags.Never ||
strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) ||
if (includes & TypeFlags.Never) {
return contains(typeSet, silentNeverType) ? silentNeverType : neverType;
}
if (strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) ||
includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) ||
includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) ||
includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) ||

View File

@ -0,0 +1,56 @@
//// [silentNeverPropagation.ts]
// Repro from #45041
type ModuleWithState<TState> = {
state: TState;
};
type State = {
a: number;
};
type MoreState = {
z: string;
};
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
const breaks = convert(
createModule({ a: 12 }, { foo() { return true } })
);
breaks.state.a
breaks.state.z
breaks.foo()
//// [silentNeverPropagation.js]
"use strict";
// Repro from #45041
var breaks = convert(createModule({ a: 12 }, { foo: function () { return true; } }));
breaks.state.a;
breaks.state.z;
breaks.foo();
//// [silentNeverPropagation.d.ts]
declare type ModuleWithState<TState> = {
state: TState;
};
declare type State = {
a: number;
};
declare type MoreState = {
z: string;
};
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
declare const breaks: ModuleWithState<{
a: number;
} & MoreState> & ModuleWithState<{
a: number;
}> & {
foo(): true;
};

View File

@ -0,0 +1,84 @@
=== tests/cases/compiler/silentNeverPropagation.ts ===
// Repro from #45041
type ModuleWithState<TState> = {
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 2, 21))
state: TState;
>state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 2, 21))
};
type State = {
>State : Symbol(State, Decl(silentNeverPropagation.ts, 4, 2))
a: number;
>a : Symbol(a, Decl(silentNeverPropagation.ts, 6, 14))
};
type MoreState = {
>MoreState : Symbol(MoreState, Decl(silentNeverPropagation.ts, 8, 2))
z: string;
>z : Symbol(z, Decl(silentNeverPropagation.ts, 10, 18))
};
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
>createModule : Symbol(createModule, Decl(silentNeverPropagation.ts, 12, 2))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 14, 30))
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 14, 37))
>state : Symbol(state, Decl(silentNeverPropagation.ts, 14, 48))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 14, 30))
>actions : Symbol(actions, Decl(silentNeverPropagation.ts, 14, 62))
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 14, 37))
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 14, 30))
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 14, 37))
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
>convert : Symbol(convert, Decl(silentNeverPropagation.ts, 14, 118))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 16, 25))
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 16, 32))
>m : Symbol(m, Decl(silentNeverPropagation.ts, 16, 43))
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 16, 25))
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 16, 32))
>ModuleWithState : Symbol(ModuleWithState, Decl(silentNeverPropagation.ts, 0, 0))
>TState : Symbol(TState, Decl(silentNeverPropagation.ts, 16, 25))
>MoreState : Symbol(MoreState, Decl(silentNeverPropagation.ts, 8, 2))
>TActions : Symbol(TActions, Decl(silentNeverPropagation.ts, 16, 32))
const breaks = convert(
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
>convert : Symbol(convert, Decl(silentNeverPropagation.ts, 14, 118))
createModule({ a: 12 }, { foo() { return true } })
>createModule : Symbol(createModule, Decl(silentNeverPropagation.ts, 12, 2))
>a : Symbol(a, Decl(silentNeverPropagation.ts, 19, 18))
>foo : Symbol(foo, Decl(silentNeverPropagation.ts, 19, 29))
);
breaks.state.a
>breaks.state.a : Symbol(a, Decl(silentNeverPropagation.ts, 19, 18))
>breaks.state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
>state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
>a : Symbol(a, Decl(silentNeverPropagation.ts, 19, 18))
breaks.state.z
>breaks.state.z : Symbol(z, Decl(silentNeverPropagation.ts, 10, 18))
>breaks.state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
>state : Symbol(state, Decl(silentNeverPropagation.ts, 2, 32), Decl(silentNeverPropagation.ts, 2, 32))
>z : Symbol(z, Decl(silentNeverPropagation.ts, 10, 18))
breaks.foo()
>breaks.foo : Symbol(foo, Decl(silentNeverPropagation.ts, 19, 29))
>breaks : Symbol(breaks, Decl(silentNeverPropagation.ts, 18, 5))
>foo : Symbol(foo, Decl(silentNeverPropagation.ts, 19, 29))

View File

@ -0,0 +1,73 @@
=== tests/cases/compiler/silentNeverPropagation.ts ===
// Repro from #45041
type ModuleWithState<TState> = {
>ModuleWithState : ModuleWithState<TState>
state: TState;
>state : TState
};
type State = {
>State : State
a: number;
>a : number
};
type MoreState = {
>MoreState : MoreState
z: string;
>z : string
};
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
>createModule : <TState, TActions>(state: TState, actions: TActions) => ModuleWithState<TState> & TActions
>state : TState
>actions : TActions
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
>convert : <TState, TActions>(m: ModuleWithState<TState> & TActions) => ModuleWithState<TState & MoreState> & TActions
>m : ModuleWithState<TState> & TActions
const breaks = convert(
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
>convert( createModule({ a: 12 }, { foo() { return true } })) : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
>convert : <TState, TActions>(m: ModuleWithState<TState> & TActions) => ModuleWithState<TState & MoreState> & TActions
createModule({ a: 12 }, { foo() { return true } })
>createModule({ a: 12 }, { foo() { return true } }) : ModuleWithState<{ a: number; }> & { foo(): true; }
>createModule : <TState, TActions>(state: TState, actions: TActions) => ModuleWithState<TState> & TActions
>{ a: 12 } : { a: number; }
>a : number
>12 : 12
>{ foo() { return true } } : { foo(): true; }
>foo : () => true
>true : true
);
breaks.state.a
>breaks.state.a : number
>breaks.state : { a: number; } & MoreState
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
>state : { a: number; } & MoreState
>a : number
breaks.state.z
>breaks.state.z : string
>breaks.state : { a: number; } & MoreState
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
>state : { a: number; } & MoreState
>z : string
breaks.foo()
>breaks.foo() : true
>breaks.foo : () => true
>breaks : ModuleWithState<{ a: number; } & MoreState> & ModuleWithState<{ a: number; }> & { foo(): true; }
>foo : () => true

View File

@ -0,0 +1,28 @@
// @strict: true
// @declaration: true
// Repro from #45041
type ModuleWithState<TState> = {
state: TState;
};
type State = {
a: number;
};
type MoreState = {
z: string;
};
declare function createModule<TState, TActions>(state: TState, actions: TActions): ModuleWithState<TState> & TActions;
declare function convert<TState, TActions>(m: ModuleWithState<TState> & TActions): ModuleWithState<TState & MoreState> & TActions;
const breaks = convert(
createModule({ a: 12 }, { foo() { return true } })
);
breaks.state.a
breaks.state.z
breaks.foo()