mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-10 00:20:22 -06:00
Port "Improve type discrimination algorithm" from tsgo (#61828)
This commit is contained in:
parent
0dfd0c2143
commit
12e09f44f6
@ -24802,11 +24802,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
if (include[i]) {
|
||||
const targetType = getTypeOfPropertyOrIndexSignatureOfType(types[i], propertyName);
|
||||
if (targetType && someType(getDiscriminatingType(), t => !!related(t, targetType))) {
|
||||
matched = true;
|
||||
}
|
||||
else {
|
||||
include[i] = Ternary.Maybe;
|
||||
if (targetType) {
|
||||
if (someType(getDiscriminatingType(), t => !!related(t, targetType))) {
|
||||
matched = true;
|
||||
}
|
||||
else {
|
||||
include[i] = Ternary.Maybe;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,7 +370,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
|
||||
);
|
||||
|
||||
let fix: FixAddNewImport | ImportFixWithModuleSpecifier;
|
||||
if (existingFix && importKind !== ImportKind.Namespace) {
|
||||
if (existingFix && importKind !== ImportKind.Namespace && existingFix.kind !== ImportFixKind.UseNamespace && existingFix.kind !== ImportFixKind.JsdocTypeImport) {
|
||||
fix = {
|
||||
...existingFix,
|
||||
addAsTypeOnly,
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
discriminateWithMissingProperty.ts(12,5): error TS2345: Argument of type '{ mode: "numeric"; data: Uint8Array<ArrayBuffer>; }' is not assignable to parameter of type 'Arg'.
|
||||
Types of property 'data' are incompatible.
|
||||
Type 'Uint8Array<ArrayBuffer>' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== discriminateWithMissingProperty.ts (1 errors) ====
|
||||
type Arg = {
|
||||
mode: "numeric",
|
||||
data: number,
|
||||
} | {
|
||||
mode: "alphabetic",
|
||||
data: string,
|
||||
} | {
|
||||
data: string | Uint8Array;
|
||||
}
|
||||
|
||||
declare function foo(arg: Arg): void;
|
||||
foo({ mode: "numeric", data: new Uint8Array([30]) }); // Should error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ mode: "numeric"; data: Uint8Array<ArrayBuffer>; }' is not assignable to parameter of type 'Arg'.
|
||||
!!! error TS2345: Types of property 'data' are incompatible.
|
||||
!!! error TS2345: Type 'Uint8Array<ArrayBuffer>' is not assignable to type 'number'.
|
||||
28
tests/baselines/reference/missingDiscriminants.errors.txt
Normal file
28
tests/baselines/reference/missingDiscriminants.errors.txt
Normal file
@ -0,0 +1,28 @@
|
||||
missingDiscriminants.ts(17,23): error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
|
||||
missingDiscriminants.ts(18,34): error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
|
||||
|
||||
|
||||
==== missingDiscriminants.ts (2 errors) ====
|
||||
// https://github.com/microsoft/typescript-go/issues/1020
|
||||
|
||||
type Thing =
|
||||
| { str: "a", num: 0 }
|
||||
| { str: "b" }
|
||||
| { num: 1 }
|
||||
|
||||
const thing1: Thing = { str: "a", num: 0 }
|
||||
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
|
||||
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
|
||||
|
||||
type Item =
|
||||
| { kind: "a", subkind: 0, value: string }
|
||||
| { kind: "a", subkind: 1, value: number }
|
||||
| { kind: "b" }
|
||||
|
||||
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
|
||||
~~~~~~~
|
||||
!!! error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
|
||||
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
|
||||
~~~~~~~
|
||||
!!! error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
|
||||
|
||||
64
tests/baselines/reference/missingDiscriminants.symbols
Normal file
64
tests/baselines/reference/missingDiscriminants.symbols
Normal file
@ -0,0 +1,64 @@
|
||||
//// [tests/cases/compiler/missingDiscriminants.ts] ////
|
||||
|
||||
=== missingDiscriminants.ts ===
|
||||
// https://github.com/microsoft/typescript-go/issues/1020
|
||||
|
||||
type Thing =
|
||||
>Thing : Symbol(Thing, Decl(missingDiscriminants.ts, 0, 0))
|
||||
|
||||
| { str: "a", num: 0 }
|
||||
>str : Symbol(str, Decl(missingDiscriminants.ts, 3, 5))
|
||||
>num : Symbol(num, Decl(missingDiscriminants.ts, 3, 15))
|
||||
|
||||
| { str: "b" }
|
||||
>str : Symbol(str, Decl(missingDiscriminants.ts, 4, 5))
|
||||
|
||||
| { num: 1 }
|
||||
>num : Symbol(num, Decl(missingDiscriminants.ts, 5, 5))
|
||||
|
||||
const thing1: Thing = { str: "a", num: 0 }
|
||||
>thing1 : Symbol(thing1, Decl(missingDiscriminants.ts, 7, 5))
|
||||
>Thing : Symbol(Thing, Decl(missingDiscriminants.ts, 0, 0))
|
||||
>str : Symbol(str, Decl(missingDiscriminants.ts, 7, 23))
|
||||
>num : Symbol(num, Decl(missingDiscriminants.ts, 7, 33))
|
||||
|
||||
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
|
||||
>thing2 : Symbol(thing2, Decl(missingDiscriminants.ts, 8, 5))
|
||||
>Thing : Symbol(Thing, Decl(missingDiscriminants.ts, 0, 0))
|
||||
>str : Symbol(str, Decl(missingDiscriminants.ts, 8, 23))
|
||||
>num : Symbol(num, Decl(missingDiscriminants.ts, 8, 33))
|
||||
|
||||
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
|
||||
>thing3 : Symbol(thing3, Decl(missingDiscriminants.ts, 9, 5))
|
||||
>Thing : Symbol(Thing, Decl(missingDiscriminants.ts, 0, 0))
|
||||
>num : Symbol(num, Decl(missingDiscriminants.ts, 9, 23))
|
||||
>str : Symbol(str, Decl(missingDiscriminants.ts, 9, 31))
|
||||
|
||||
type Item =
|
||||
>Item : Symbol(Item, Decl(missingDiscriminants.ts, 9, 42))
|
||||
|
||||
| { kind: "a", subkind: 0, value: string }
|
||||
>kind : Symbol(kind, Decl(missingDiscriminants.ts, 12, 5))
|
||||
>subkind : Symbol(subkind, Decl(missingDiscriminants.ts, 12, 16))
|
||||
>value : Symbol(value, Decl(missingDiscriminants.ts, 12, 28))
|
||||
|
||||
| { kind: "a", subkind: 1, value: number }
|
||||
>kind : Symbol(kind, Decl(missingDiscriminants.ts, 13, 5))
|
||||
>subkind : Symbol(subkind, Decl(missingDiscriminants.ts, 13, 16))
|
||||
>value : Symbol(value, Decl(missingDiscriminants.ts, 13, 28))
|
||||
|
||||
| { kind: "b" }
|
||||
>kind : Symbol(kind, Decl(missingDiscriminants.ts, 14, 5))
|
||||
|
||||
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
|
||||
>item1 : Symbol(item1, Decl(missingDiscriminants.ts, 16, 5))
|
||||
>Item : Symbol(Item, Decl(missingDiscriminants.ts, 9, 42))
|
||||
>subkind : Symbol(subkind, Decl(missingDiscriminants.ts, 16, 21))
|
||||
>kind : Symbol(kind, Decl(missingDiscriminants.ts, 16, 33))
|
||||
|
||||
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
|
||||
>item2 : Symbol(item2, Decl(missingDiscriminants.ts, 17, 5))
|
||||
>Item : Symbol(Item, Decl(missingDiscriminants.ts, 9, 42))
|
||||
>kind : Symbol(kind, Decl(missingDiscriminants.ts, 17, 21))
|
||||
>subkind : Symbol(subkind, Decl(missingDiscriminants.ts, 17, 32))
|
||||
|
||||
117
tests/baselines/reference/missingDiscriminants.types
Normal file
117
tests/baselines/reference/missingDiscriminants.types
Normal file
@ -0,0 +1,117 @@
|
||||
//// [tests/cases/compiler/missingDiscriminants.ts] ////
|
||||
|
||||
=== missingDiscriminants.ts ===
|
||||
// https://github.com/microsoft/typescript-go/issues/1020
|
||||
|
||||
type Thing =
|
||||
>Thing : Thing
|
||||
> : ^^^^^
|
||||
|
||||
| { str: "a", num: 0 }
|
||||
>str : "a"
|
||||
> : ^^^
|
||||
>num : 0
|
||||
> : ^
|
||||
|
||||
| { str: "b" }
|
||||
>str : "b"
|
||||
> : ^^^
|
||||
|
||||
| { num: 1 }
|
||||
>num : 1
|
||||
> : ^
|
||||
|
||||
const thing1: Thing = { str: "a", num: 0 }
|
||||
>thing1 : Thing
|
||||
> : ^^^^^
|
||||
>{ str: "a", num: 0 } : { str: "a"; num: 0; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^
|
||||
>str : "a"
|
||||
> : ^^^
|
||||
>"a" : "a"
|
||||
> : ^^^
|
||||
>num : 0
|
||||
> : ^
|
||||
>0 : 0
|
||||
> : ^
|
||||
|
||||
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
|
||||
>thing2 : Thing
|
||||
> : ^^^^^
|
||||
>{ str: "b", num: 1 } : { str: "b"; num: 1; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^
|
||||
>str : "b"
|
||||
> : ^^^
|
||||
>"b" : "b"
|
||||
> : ^^^
|
||||
>num : 1
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
|
||||
>thing3 : Thing
|
||||
> : ^^^^^
|
||||
>{ num: 1, str: "b" } : { num: 1; str: "b"; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^
|
||||
>num : 1
|
||||
> : ^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>str : "b"
|
||||
> : ^^^
|
||||
>"b" : "b"
|
||||
> : ^^^
|
||||
|
||||
type Item =
|
||||
>Item : Item
|
||||
> : ^^^^
|
||||
|
||||
| { kind: "a", subkind: 0, value: string }
|
||||
>kind : "a"
|
||||
> : ^^^
|
||||
>subkind : 0
|
||||
> : ^
|
||||
>value : string
|
||||
> : ^^^^^^
|
||||
|
||||
| { kind: "a", subkind: 1, value: number }
|
||||
>kind : "a"
|
||||
> : ^^^
|
||||
>subkind : 1
|
||||
> : ^
|
||||
>value : number
|
||||
> : ^^^^^^
|
||||
|
||||
| { kind: "b" }
|
||||
>kind : "b"
|
||||
> : ^^^
|
||||
|
||||
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
|
||||
>item1 : Item
|
||||
> : ^^^^
|
||||
>{ subkind: 1, kind: "b" } : { subkind: number; kind: "b"; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>subkind : number
|
||||
> : ^^^^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
>kind : "b"
|
||||
> : ^^^
|
||||
>"b" : "b"
|
||||
> : ^^^
|
||||
|
||||
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
|
||||
>item2 : Item
|
||||
> : ^^^^
|
||||
>{ kind: "b", subkind: 1 } : { kind: "b"; subkind: number; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>kind : "b"
|
||||
> : ^^^
|
||||
>"b" : "b"
|
||||
> : ^^^
|
||||
>subkind : number
|
||||
> : ^^^^^^
|
||||
>1 : 1
|
||||
> : ^
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//// [tests/cases/compiler/promiseType.ts] ////
|
||||
|
||||
=== Performance Stats ===
|
||||
Instantiation count: 2,500
|
||||
Instantiation count: 1,000
|
||||
|
||||
=== promiseType.ts ===
|
||||
declare var p: Promise<boolean>;
|
||||
|
||||
21
tests/cases/compiler/missingDiscriminants.ts
Normal file
21
tests/cases/compiler/missingDiscriminants.ts
Normal file
@ -0,0 +1,21 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
// https://github.com/microsoft/typescript-go/issues/1020
|
||||
|
||||
type Thing =
|
||||
| { str: "a", num: 0 }
|
||||
| { str: "b" }
|
||||
| { num: 1 }
|
||||
|
||||
const thing1: Thing = { str: "a", num: 0 }
|
||||
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
|
||||
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
|
||||
|
||||
type Item =
|
||||
| { kind: "a", subkind: 0, value: string }
|
||||
| { kind: "a", subkind: 1, value: number }
|
||||
| { kind: "b" }
|
||||
|
||||
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
|
||||
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
|
||||
Loading…
x
Reference in New Issue
Block a user