mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-12 23:36:28 -05:00
Fixed type predicate inference for discriminated union parameters (#57952)
This commit is contained in:
committed by
GitHub
parent
4cedfe40b0
commit
42a215c8fb
@@ -37690,8 +37690,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
{ flags: FlowFlags.Start };
|
||||
const trueCondition: FlowCondition = {
|
||||
flags: FlowFlags.TrueCondition,
|
||||
node: expr,
|
||||
antecedent,
|
||||
node: expr,
|
||||
};
|
||||
|
||||
const trueType = getFlowTypeOfReference(param.name, initType, initType, func, trueCondition);
|
||||
@@ -37700,10 +37700,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// "x is T" means that x is T if and only if it returns true. If it returns false then x is not T.
|
||||
// This means that if the function is called with an argument of type trueType, there can't be anything left in the `else` branch. It must reduce to `never`.
|
||||
const falseCondition: FlowCondition = {
|
||||
...trueCondition,
|
||||
flags: FlowFlags.FalseCondition,
|
||||
antecedent,
|
||||
node: expr,
|
||||
};
|
||||
const falseSubtype = getFlowTypeOfReference(param.name, trueType, trueType, func, falseCondition);
|
||||
const falseSubtype = getFlowTypeOfReference(param.name, initType, trueType, func, falseCondition);
|
||||
return falseSubtype.flags & TypeFlags.Never ? trueType : undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,4 +315,14 @@ inferTypePredicates.ts(205,7): error TS2741: Property 'z' is missing in type 'C1
|
||||
function inferWithRest(x: string | null, ...f: ["a", "b"]) {
|
||||
return typeof x === 'string';
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/57947
|
||||
declare const foobar:
|
||||
| { type: "foo"; foo: number }
|
||||
| { type: "bar"; bar: string };
|
||||
|
||||
const foobarPred = (fb: typeof foobar) => fb.type === "foo";
|
||||
if (foobarPred(foobar)) {
|
||||
foobar.foo;
|
||||
}
|
||||
|
||||
@@ -269,6 +269,16 @@ const noInferenceFromImpossibleRest = (...f: []) => typeof f === "undefined";
|
||||
function inferWithRest(x: string | null, ...f: ["a", "b"]) {
|
||||
return typeof x === 'string';
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/57947
|
||||
declare const foobar:
|
||||
| { type: "foo"; foo: number }
|
||||
| { type: "bar"; bar: string };
|
||||
|
||||
const foobarPred = (fb: typeof foobar) => fb.type === "foo";
|
||||
if (foobarPred(foobar)) {
|
||||
foobar.foo;
|
||||
}
|
||||
|
||||
|
||||
//// [inferTypePredicates.js]
|
||||
@@ -524,6 +534,10 @@ function inferWithRest(x) {
|
||||
}
|
||||
return typeof x === 'string';
|
||||
}
|
||||
var foobarPred = function (fb) { return fb.type === "foo"; };
|
||||
if (foobarPred(foobar)) {
|
||||
foobar.foo;
|
||||
}
|
||||
|
||||
|
||||
//// [inferTypePredicates.d.ts]
|
||||
@@ -605,3 +619,14 @@ declare function narrowFromAny(x: any): x is number;
|
||||
declare const noInferenceFromRest: (f_0: "a" | "b") => boolean;
|
||||
declare const noInferenceFromImpossibleRest: () => boolean;
|
||||
declare function inferWithRest(x: string | null, ...f: ["a", "b"]): x is string;
|
||||
declare const foobar: {
|
||||
type: "foo";
|
||||
foo: number;
|
||||
} | {
|
||||
type: "bar";
|
||||
bar: string;
|
||||
};
|
||||
declare const foobarPred: (fb: typeof foobar) => fb is {
|
||||
type: "foo";
|
||||
foo: number;
|
||||
};
|
||||
|
||||
@@ -747,3 +747,33 @@ function inferWithRest(x: string | null, ...f: ["a", "b"]) {
|
||||
>x : Symbol(x, Decl(inferTypePredicates.ts, 265, 23))
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/57947
|
||||
declare const foobar:
|
||||
>foobar : Symbol(foobar, Decl(inferTypePredicates.ts, 270, 13))
|
||||
|
||||
| { type: "foo"; foo: number }
|
||||
>type : Symbol(type, Decl(inferTypePredicates.ts, 271, 5))
|
||||
>foo : Symbol(foo, Decl(inferTypePredicates.ts, 271, 18))
|
||||
|
||||
| { type: "bar"; bar: string };
|
||||
>type : Symbol(type, Decl(inferTypePredicates.ts, 272, 5))
|
||||
>bar : Symbol(bar, Decl(inferTypePredicates.ts, 272, 18))
|
||||
|
||||
const foobarPred = (fb: typeof foobar) => fb.type === "foo";
|
||||
>foobarPred : Symbol(foobarPred, Decl(inferTypePredicates.ts, 274, 5))
|
||||
>fb : Symbol(fb, Decl(inferTypePredicates.ts, 274, 20))
|
||||
>foobar : Symbol(foobar, Decl(inferTypePredicates.ts, 270, 13))
|
||||
>fb.type : Symbol(type, Decl(inferTypePredicates.ts, 271, 5), Decl(inferTypePredicates.ts, 272, 5))
|
||||
>fb : Symbol(fb, Decl(inferTypePredicates.ts, 274, 20))
|
||||
>type : Symbol(type, Decl(inferTypePredicates.ts, 271, 5), Decl(inferTypePredicates.ts, 272, 5))
|
||||
|
||||
if (foobarPred(foobar)) {
|
||||
>foobarPred : Symbol(foobarPred, Decl(inferTypePredicates.ts, 274, 5))
|
||||
>foobar : Symbol(foobar, Decl(inferTypePredicates.ts, 270, 13))
|
||||
|
||||
foobar.foo;
|
||||
>foobar.foo : Symbol(foo, Decl(inferTypePredicates.ts, 271, 18))
|
||||
>foobar : Symbol(foobar, Decl(inferTypePredicates.ts, 270, 13))
|
||||
>foo : Symbol(foo, Decl(inferTypePredicates.ts, 271, 18))
|
||||
}
|
||||
|
||||
|
||||
@@ -1595,3 +1595,57 @@ function inferWithRest(x: string | null, ...f: ["a", "b"]) {
|
||||
> : ^^^^^^^^
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/57947
|
||||
declare const foobar:
|
||||
>foobar : { type: "foo"; foo: number; } | { type: "bar"; bar: string; }
|
||||
> : ^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^ ^^^
|
||||
|
||||
| { type: "foo"; foo: number }
|
||||
>type : "foo"
|
||||
> : ^^^^^
|
||||
>foo : number
|
||||
> : ^^^^^^
|
||||
|
||||
| { type: "bar"; bar: string };
|
||||
>type : "bar"
|
||||
> : ^^^^^
|
||||
>bar : string
|
||||
> : ^^^^^^
|
||||
|
||||
const foobarPred = (fb: typeof foobar) => fb.type === "foo";
|
||||
>foobarPred : (fb: typeof foobar) => fb is { type: "foo"; foo: number; }
|
||||
> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>(fb: typeof foobar) => fb.type === "foo" : (fb: typeof foobar) => fb is { type: "foo"; foo: number; }
|
||||
> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>fb : { type: "foo"; foo: number; } | { type: "bar"; bar: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foobar : { type: "foo"; foo: number; } | { type: "bar"; bar: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>fb.type === "foo" : boolean
|
||||
> : ^^^^^^^
|
||||
>fb.type : "bar" | "foo"
|
||||
> : ^^^^^^^^^^^^^
|
||||
>fb : { type: "foo"; foo: number; } | { type: "bar"; bar: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>type : "bar" | "foo"
|
||||
> : ^^^^^^^^^^^^^
|
||||
>"foo" : "foo"
|
||||
> : ^^^^^
|
||||
|
||||
if (foobarPred(foobar)) {
|
||||
>foobarPred(foobar) : boolean
|
||||
> : ^^^^^^^
|
||||
>foobarPred : (fb: { type: "foo"; foo: number; } | { type: "bar"; bar: string; }) => fb is { type: "foo"; foo: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foobar : { type: "foo"; foo: number; } | { type: "bar"; bar: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
foobar.foo;
|
||||
>foobar.foo : number
|
||||
> : ^^^^^^
|
||||
>foobar : { type: "foo"; foo: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>foo : number
|
||||
> : ^^^^^^
|
||||
}
|
||||
|
||||
|
||||
@@ -269,3 +269,13 @@ const noInferenceFromImpossibleRest = (...f: []) => typeof f === "undefined";
|
||||
function inferWithRest(x: string | null, ...f: ["a", "b"]) {
|
||||
return typeof x === 'string';
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/57947
|
||||
declare const foobar:
|
||||
| { type: "foo"; foo: number }
|
||||
| { type: "bar"; bar: string };
|
||||
|
||||
const foobarPred = (fb: typeof foobar) => fb.type === "foo";
|
||||
if (foobarPred(foobar)) {
|
||||
foobar.foo;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user