Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27888,24 +27888,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
for (const type of types) {
if (type.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive)) {
const discriminant = getTypeOfPropertyOfType(type, name);
if (discriminant) {
if (!isLiteralType(discriminant)) {
return undefined;
}
let duplicate = false;
forEachType(discriminant, t => {
const id = getTypeId(getRegularTypeOfLiteralType(t));
const existing = map.get(id);
if (!existing) {
map.set(id, type);
}
else if (existing !== unknownType) {
map.set(id, unknownType);
duplicate = true;
}
});
if (!duplicate) count++;
if (!discriminant || !isLiteralType(discriminant)) {
return undefined;
}
let duplicate = false;
forEachType(discriminant, t => {
const id = getTypeId(getRegularTypeOfLiteralType(t));
const existing = map.get(id);
if (!existing) {
map.set(id, type);
}
else if (existing !== unknownType) {
map.set(id, unknownType);
duplicate = true;
}
});
if (!duplicate) count++;
}
}
return count >= 10 && count * 2 >= types.length ? map : undefined;
Expand Down
41 changes: 41 additions & 0 deletions tests/baselines/reference/missingDiscriminants2.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
missingDiscriminants2.ts(30,23): error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
missingDiscriminants2.ts(31,34): error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.


==== missingDiscriminants2.ts (2 errors) ====
// https://github.com/microsoft/typescript-go/issues/1020

type Thing =
| { str: "a", num: 0 }
| { str: "b" }
| { str: "c" }
| { str: "d" }
| { str: "e" }
| { str: "f" }
| { str: "g" }
| { str: "h" }
| { str: "i" }
| { str: "j" }
| { str: "k" }
| { str: "l" }
| { str: "m" }
| { str: "n" }
| { str: "o" }
| { 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"; }'.

103 changes: 103 additions & 0 deletions tests/baselines/reference/missingDiscriminants2.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//// [tests/cases/compiler/missingDiscriminants2.ts] ////

=== missingDiscriminants2.ts ===
// https://github.com/microsoft/typescript-go/issues/1020

type Thing =
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))

| { str: "a", num: 0 }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 3, 5))
>num : Symbol(num, Decl(missingDiscriminants2.ts, 3, 15))

| { str: "b" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 4, 5))

| { str: "c" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 5, 5))

| { str: "d" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 6, 5))

| { str: "e" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 7, 5))

| { str: "f" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 8, 5))

| { str: "g" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 9, 5))

| { str: "h" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 10, 5))

| { str: "i" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 11, 5))

| { str: "j" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 12, 5))

| { str: "k" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 13, 5))

| { str: "l" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 14, 5))

| { str: "m" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 15, 5))

| { str: "n" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 16, 5))

| { str: "o" }
>str : Symbol(str, Decl(missingDiscriminants2.ts, 17, 5))

| { num: 1 }
>num : Symbol(num, Decl(missingDiscriminants2.ts, 18, 5))

const thing1: Thing = { str: "a", num: 0 }
>thing1 : Symbol(thing1, Decl(missingDiscriminants2.ts, 20, 5))
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))
>str : Symbol(str, Decl(missingDiscriminants2.ts, 20, 23))
>num : Symbol(num, Decl(missingDiscriminants2.ts, 20, 33))

const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
>thing2 : Symbol(thing2, Decl(missingDiscriminants2.ts, 21, 5))
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))
>str : Symbol(str, Decl(missingDiscriminants2.ts, 21, 23))
>num : Symbol(num, Decl(missingDiscriminants2.ts, 21, 33))

const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
>thing3 : Symbol(thing3, Decl(missingDiscriminants2.ts, 22, 5))
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))
>num : Symbol(num, Decl(missingDiscriminants2.ts, 22, 23))
>str : Symbol(str, Decl(missingDiscriminants2.ts, 22, 31))

type Item =
>Item : Symbol(Item, Decl(missingDiscriminants2.ts, 22, 42))

| { kind: "a", subkind: 0, value: string }
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 25, 5))
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 25, 16))
>value : Symbol(value, Decl(missingDiscriminants2.ts, 25, 28))

| { kind: "a", subkind: 1, value: number }
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 26, 5))
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 26, 16))
>value : Symbol(value, Decl(missingDiscriminants2.ts, 26, 28))

| { kind: "b" }
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 27, 5))

const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
>item1 : Symbol(item1, Decl(missingDiscriminants2.ts, 29, 5))
>Item : Symbol(Item, Decl(missingDiscriminants2.ts, 22, 42))
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 29, 21))
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 29, 33))

const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
>item2 : Symbol(item2, Decl(missingDiscriminants2.ts, 30, 5))
>Item : Symbol(Item, Decl(missingDiscriminants2.ts, 22, 42))
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 30, 21))
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 30, 32))

169 changes: 169 additions & 0 deletions tests/baselines/reference/missingDiscriminants2.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
//// [tests/cases/compiler/missingDiscriminants2.ts] ////

=== missingDiscriminants2.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"
> : ^^^

| { str: "c" }
>str : "c"
> : ^^^

| { str: "d" }
>str : "d"
> : ^^^

| { str: "e" }
>str : "e"
> : ^^^

| { str: "f" }
>str : "f"
> : ^^^

| { str: "g" }
>str : "g"
> : ^^^

| { str: "h" }
>str : "h"
> : ^^^

| { str: "i" }
>str : "i"
> : ^^^

| { str: "j" }
>str : "j"
> : ^^^

| { str: "k" }
>str : "k"
> : ^^^

| { str: "l" }
>str : "l"
> : ^^^

| { str: "m" }
>str : "m"
> : ^^^

| { str: "n" }
>str : "n"
> : ^^^

| { str: "o" }
>str : "o"
> : ^^^

| { 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
> : ^

34 changes: 34 additions & 0 deletions tests/cases/compiler/missingDiscriminants2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// @strict: true
// @noEmit: true

// https://github.com/microsoft/typescript-go/issues/1020

type Thing =
| { str: "a", num: 0 }
| { str: "b" }
| { str: "c" }
| { str: "d" }
| { str: "e" }
| { str: "f" }
| { str: "g" }
| { str: "h" }
| { str: "i" }
| { str: "j" }
| { str: "k" }
| { str: "l" }
| { str: "m" }
| { str: "n" }
| { str: "o" }
| { 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