mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint
This commit is contained in:
commit
6988e25985
@ -14266,20 +14266,25 @@ namespace ts {
|
||||
function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary): Type | undefined;
|
||||
function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue: Type): Type;
|
||||
function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: Type) {
|
||||
let match: Type | undefined;
|
||||
// undefined=unknown, true=discriminated, false=not discriminated
|
||||
// The state of each type progresses from left to right. Discriminated types stop at 'true'.
|
||||
const discriminable = target.types.map(_ => undefined) as (boolean | undefined)[];
|
||||
for (const [getDiscriminatingType, propertyName] of discriminators) {
|
||||
let i = 0;
|
||||
for (const type of target.types) {
|
||||
const targetType = getTypeOfPropertyOfType(type, propertyName);
|
||||
if (targetType && related(getDiscriminatingType(), targetType)) {
|
||||
if (match) {
|
||||
if (type === match) continue; // Finding multiple fields which discriminate to the same type is fine
|
||||
return defaultValue;
|
||||
}
|
||||
match = type;
|
||||
discriminable[i] = discriminable[i] === undefined ? true : discriminable[i];
|
||||
}
|
||||
else {
|
||||
discriminable[i] = false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return match || defaultValue;
|
||||
const match = discriminable.indexOf(/*searchElement*/ true);
|
||||
// make sure exactly 1 matches before returning it
|
||||
return match === -1 || discriminable.indexOf(/*searchElement*/ true, match + 1) !== -1 ? defaultValue : target.types[match];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -980,4 +980,12 @@ namespace ts.server {
|
||||
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
|
||||
ts.sys.tryEnableSourceMapsForHost();
|
||||
}
|
||||
|
||||
// Overwrites the current console messages to instead write to
|
||||
// the log. This is so that language service plugins which use
|
||||
// console.log don't break the message passing between tsserver
|
||||
// and the client
|
||||
console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Info);
|
||||
console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Err);
|
||||
console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Err);
|
||||
}
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
tests/cases/compiler/excessPropertyCheckWithMultipleDiscriminants.ts(30,5): error TS2322: Type '{ type: "number"; value: number; multipleOf: number; format: string; }' is not assignable to type 'Primitive'.
|
||||
Object literal may only specify known properties, and 'multipleOf' does not exist in type 'Float'.
|
||||
tests/cases/compiler/excessPropertyCheckWithMultipleDiscriminants.ts(41,5): error TS2322: Type '{ p1: "left"; p2: false; p3: number; p4: string; }' is not assignable to type 'DisjointDiscriminants'.
|
||||
Object literal may only specify known properties, and 'p3' does not exist in type '{ p1: "left"; p2: boolean; }'.
|
||||
tests/cases/compiler/excessPropertyCheckWithMultipleDiscriminants.ts(57,5): error TS2322: Type '{ p1: "right"; p2: false; p3: number; p4: string; }' is not assignable to type 'DisjointDiscriminants'.
|
||||
Object literal may only specify known properties, and 'p3' does not exist in type '{ p1: "right"; p2: false; p4: string; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/excessPropertyCheckWithMultipleDiscriminants.ts (3 errors) ====
|
||||
// Repro from #32657
|
||||
|
||||
interface Base<T> {
|
||||
value: T;
|
||||
}
|
||||
|
||||
interface Int extends Base<number> {
|
||||
type: "integer";
|
||||
multipleOf?: number;
|
||||
}
|
||||
|
||||
interface Float extends Base<number> {
|
||||
type: "number";
|
||||
}
|
||||
|
||||
interface Str extends Base<string> {
|
||||
type: "string";
|
||||
format?: string;
|
||||
}
|
||||
|
||||
interface Bool extends Base<boolean> {
|
||||
type: "boolean";
|
||||
}
|
||||
|
||||
type Primitive = Int | Float | Str | Bool;
|
||||
|
||||
const foo: Primitive = {
|
||||
type: "number",
|
||||
value: 10,
|
||||
multipleOf: 5, // excess property
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ type: "number"; value: number; multipleOf: number; format: string; }' is not assignable to type 'Primitive'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'multipleOf' does not exist in type 'Float'.
|
||||
format: "what?"
|
||||
}
|
||||
|
||||
|
||||
type DisjointDiscriminants = { p1: 'left'; p2: true; p3: number } | { p1: 'right'; p2: false; p4: string } | { p1: 'left'; p2: boolean };
|
||||
|
||||
// This has excess error because variant three is the only applicable case.
|
||||
const a: DisjointDiscriminants = {
|
||||
p1: 'left',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ p1: "left"; p2: false; p3: number; p4: string; }' is not assignable to type 'DisjointDiscriminants'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'p3' does not exist in type '{ p1: "left"; p2: boolean; }'.
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
// This has no excess error because variant one and three are both applicable.
|
||||
const b: DisjointDiscriminants = {
|
||||
p1: 'left',
|
||||
p2: true,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
// This has excess error because variant two is the only applicable case
|
||||
const c: DisjointDiscriminants = {
|
||||
p1: 'right',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ p1: "right"; p2: false; p3: number; p4: string; }' is not assignable to type 'DisjointDiscriminants'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'p3' does not exist in type '{ p1: "right"; p2: false; p4: string; }'.
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
//// [excessPropertyCheckWithMultipleDiscriminants.ts]
|
||||
// Repro from #32657
|
||||
|
||||
interface Base<T> {
|
||||
value: T;
|
||||
}
|
||||
|
||||
interface Int extends Base<number> {
|
||||
type: "integer";
|
||||
multipleOf?: number;
|
||||
}
|
||||
|
||||
interface Float extends Base<number> {
|
||||
type: "number";
|
||||
}
|
||||
|
||||
interface Str extends Base<string> {
|
||||
type: "string";
|
||||
format?: string;
|
||||
}
|
||||
|
||||
interface Bool extends Base<boolean> {
|
||||
type: "boolean";
|
||||
}
|
||||
|
||||
type Primitive = Int | Float | Str | Bool;
|
||||
|
||||
const foo: Primitive = {
|
||||
type: "number",
|
||||
value: 10,
|
||||
multipleOf: 5, // excess property
|
||||
format: "what?"
|
||||
}
|
||||
|
||||
|
||||
type DisjointDiscriminants = { p1: 'left'; p2: true; p3: number } | { p1: 'right'; p2: false; p4: string } | { p1: 'left'; p2: boolean };
|
||||
|
||||
// This has excess error because variant three is the only applicable case.
|
||||
const a: DisjointDiscriminants = {
|
||||
p1: 'left',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
// This has no excess error because variant one and three are both applicable.
|
||||
const b: DisjointDiscriminants = {
|
||||
p1: 'left',
|
||||
p2: true,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
// This has excess error because variant two is the only applicable case
|
||||
const c: DisjointDiscriminants = {
|
||||
p1: 'right',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
|
||||
//// [excessPropertyCheckWithMultipleDiscriminants.js]
|
||||
// Repro from #32657
|
||||
var foo = {
|
||||
type: "number",
|
||||
value: 10,
|
||||
multipleOf: 5,
|
||||
format: "what?"
|
||||
};
|
||||
// This has excess error because variant three is the only applicable case.
|
||||
var a = {
|
||||
p1: 'left',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
// This has no excess error because variant one and three are both applicable.
|
||||
var b = {
|
||||
p1: 'left',
|
||||
p2: true,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
// This has excess error because variant two is the only applicable case
|
||||
var c = {
|
||||
p1: 'right',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
@ -0,0 +1,143 @@
|
||||
=== tests/cases/compiler/excessPropertyCheckWithMultipleDiscriminants.ts ===
|
||||
// Repro from #32657
|
||||
|
||||
interface Base<T> {
|
||||
>Base : Symbol(Base, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 2, 15))
|
||||
|
||||
value: T;
|
||||
>value : Symbol(Base.value, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 2, 19))
|
||||
>T : Symbol(T, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 2, 15))
|
||||
}
|
||||
|
||||
interface Int extends Base<number> {
|
||||
>Int : Symbol(Int, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 4, 1))
|
||||
>Base : Symbol(Base, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 0, 0))
|
||||
|
||||
type: "integer";
|
||||
>type : Symbol(Int.type, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 6, 36))
|
||||
|
||||
multipleOf?: number;
|
||||
>multipleOf : Symbol(Int.multipleOf, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 7, 20))
|
||||
}
|
||||
|
||||
interface Float extends Base<number> {
|
||||
>Float : Symbol(Float, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 9, 1))
|
||||
>Base : Symbol(Base, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 0, 0))
|
||||
|
||||
type: "number";
|
||||
>type : Symbol(Float.type, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 11, 38))
|
||||
}
|
||||
|
||||
interface Str extends Base<string> {
|
||||
>Str : Symbol(Str, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 13, 1))
|
||||
>Base : Symbol(Base, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 0, 0))
|
||||
|
||||
type: "string";
|
||||
>type : Symbol(Str.type, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 15, 36))
|
||||
|
||||
format?: string;
|
||||
>format : Symbol(Str.format, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 16, 19))
|
||||
}
|
||||
|
||||
interface Bool extends Base<boolean> {
|
||||
>Bool : Symbol(Bool, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 18, 1))
|
||||
>Base : Symbol(Base, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 0, 0))
|
||||
|
||||
type: "boolean";
|
||||
>type : Symbol(Bool.type, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 20, 38))
|
||||
}
|
||||
|
||||
type Primitive = Int | Float | Str | Bool;
|
||||
>Primitive : Symbol(Primitive, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 22, 1))
|
||||
>Int : Symbol(Int, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 4, 1))
|
||||
>Float : Symbol(Float, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 9, 1))
|
||||
>Str : Symbol(Str, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 13, 1))
|
||||
>Bool : Symbol(Bool, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 18, 1))
|
||||
|
||||
const foo: Primitive = {
|
||||
>foo : Symbol(foo, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 26, 5))
|
||||
>Primitive : Symbol(Primitive, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 22, 1))
|
||||
|
||||
type: "number",
|
||||
>type : Symbol(type, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 26, 24))
|
||||
|
||||
value: 10,
|
||||
>value : Symbol(value, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 27, 19))
|
||||
|
||||
multipleOf: 5, // excess property
|
||||
>multipleOf : Symbol(multipleOf, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 28, 14))
|
||||
|
||||
format: "what?"
|
||||
>format : Symbol(format, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 29, 18))
|
||||
}
|
||||
|
||||
|
||||
type DisjointDiscriminants = { p1: 'left'; p2: true; p3: number } | { p1: 'right'; p2: false; p4: string } | { p1: 'left'; p2: boolean };
|
||||
>DisjointDiscriminants : Symbol(DisjointDiscriminants, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 31, 1))
|
||||
>p1 : Symbol(p1, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 30))
|
||||
>p2 : Symbol(p2, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 42))
|
||||
>p3 : Symbol(p3, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 52))
|
||||
>p1 : Symbol(p1, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 69))
|
||||
>p2 : Symbol(p2, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 82))
|
||||
>p4 : Symbol(p4, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 93))
|
||||
>p1 : Symbol(p1, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 110))
|
||||
>p2 : Symbol(p2, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 34, 122))
|
||||
|
||||
// This has excess error because variant three is the only applicable case.
|
||||
const a: DisjointDiscriminants = {
|
||||
>a : Symbol(a, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 37, 5))
|
||||
>DisjointDiscriminants : Symbol(DisjointDiscriminants, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 31, 1))
|
||||
|
||||
p1: 'left',
|
||||
>p1 : Symbol(p1, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 37, 34))
|
||||
|
||||
p2: false,
|
||||
>p2 : Symbol(p2, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 38, 15))
|
||||
|
||||
p3: 42,
|
||||
>p3 : Symbol(p3, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 39, 14))
|
||||
|
||||
p4: "hello"
|
||||
>p4 : Symbol(p4, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 40, 11))
|
||||
|
||||
};
|
||||
|
||||
// This has no excess error because variant one and three are both applicable.
|
||||
const b: DisjointDiscriminants = {
|
||||
>b : Symbol(b, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 45, 5))
|
||||
>DisjointDiscriminants : Symbol(DisjointDiscriminants, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 31, 1))
|
||||
|
||||
p1: 'left',
|
||||
>p1 : Symbol(p1, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 45, 34))
|
||||
|
||||
p2: true,
|
||||
>p2 : Symbol(p2, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 46, 15))
|
||||
|
||||
p3: 42,
|
||||
>p3 : Symbol(p3, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 47, 13))
|
||||
|
||||
p4: "hello"
|
||||
>p4 : Symbol(p4, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 48, 11))
|
||||
|
||||
};
|
||||
|
||||
// This has excess error because variant two is the only applicable case
|
||||
const c: DisjointDiscriminants = {
|
||||
>c : Symbol(c, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 53, 5))
|
||||
>DisjointDiscriminants : Symbol(DisjointDiscriminants, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 31, 1))
|
||||
|
||||
p1: 'right',
|
||||
>p1 : Symbol(p1, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 53, 34))
|
||||
|
||||
p2: false,
|
||||
>p2 : Symbol(p2, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 54, 16))
|
||||
|
||||
p3: 42,
|
||||
>p3 : Symbol(p3, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 55, 14))
|
||||
|
||||
p4: "hello"
|
||||
>p4 : Symbol(p4, Decl(excessPropertyCheckWithMultipleDiscriminants.ts, 56, 11))
|
||||
|
||||
};
|
||||
|
||||
@ -0,0 +1,141 @@
|
||||
=== tests/cases/compiler/excessPropertyCheckWithMultipleDiscriminants.ts ===
|
||||
// Repro from #32657
|
||||
|
||||
interface Base<T> {
|
||||
value: T;
|
||||
>value : T
|
||||
}
|
||||
|
||||
interface Int extends Base<number> {
|
||||
type: "integer";
|
||||
>type : "integer"
|
||||
|
||||
multipleOf?: number;
|
||||
>multipleOf : number
|
||||
}
|
||||
|
||||
interface Float extends Base<number> {
|
||||
type: "number";
|
||||
>type : "number"
|
||||
}
|
||||
|
||||
interface Str extends Base<string> {
|
||||
type: "string";
|
||||
>type : "string"
|
||||
|
||||
format?: string;
|
||||
>format : string
|
||||
}
|
||||
|
||||
interface Bool extends Base<boolean> {
|
||||
type: "boolean";
|
||||
>type : "boolean"
|
||||
}
|
||||
|
||||
type Primitive = Int | Float | Str | Bool;
|
||||
>Primitive : Primitive
|
||||
|
||||
const foo: Primitive = {
|
||||
>foo : Primitive
|
||||
>{ type: "number", value: 10, multipleOf: 5, // excess property format: "what?"} : { type: "number"; value: number; multipleOf: number; format: string; }
|
||||
|
||||
type: "number",
|
||||
>type : "number"
|
||||
>"number" : "number"
|
||||
|
||||
value: 10,
|
||||
>value : number
|
||||
>10 : 10
|
||||
|
||||
multipleOf: 5, // excess property
|
||||
>multipleOf : number
|
||||
>5 : 5
|
||||
|
||||
format: "what?"
|
||||
>format : string
|
||||
>"what?" : "what?"
|
||||
}
|
||||
|
||||
|
||||
type DisjointDiscriminants = { p1: 'left'; p2: true; p3: number } | { p1: 'right'; p2: false; p4: string } | { p1: 'left'; p2: boolean };
|
||||
>DisjointDiscriminants : DisjointDiscriminants
|
||||
>p1 : "left"
|
||||
>p2 : true
|
||||
>true : true
|
||||
>p3 : number
|
||||
>p1 : "right"
|
||||
>p2 : false
|
||||
>false : false
|
||||
>p4 : string
|
||||
>p1 : "left"
|
||||
>p2 : boolean
|
||||
|
||||
// This has excess error because variant three is the only applicable case.
|
||||
const a: DisjointDiscriminants = {
|
||||
>a : DisjointDiscriminants
|
||||
>{ p1: 'left', p2: false, p3: 42, p4: "hello"} : { p1: "left"; p2: false; p3: number; p4: string; }
|
||||
|
||||
p1: 'left',
|
||||
>p1 : "left"
|
||||
>'left' : "left"
|
||||
|
||||
p2: false,
|
||||
>p2 : false
|
||||
>false : false
|
||||
|
||||
p3: 42,
|
||||
>p3 : number
|
||||
>42 : 42
|
||||
|
||||
p4: "hello"
|
||||
>p4 : string
|
||||
>"hello" : "hello"
|
||||
|
||||
};
|
||||
|
||||
// This has no excess error because variant one and three are both applicable.
|
||||
const b: DisjointDiscriminants = {
|
||||
>b : DisjointDiscriminants
|
||||
>{ p1: 'left', p2: true, p3: 42, p4: "hello"} : { p1: "left"; p2: true; p3: number; p4: string; }
|
||||
|
||||
p1: 'left',
|
||||
>p1 : "left"
|
||||
>'left' : "left"
|
||||
|
||||
p2: true,
|
||||
>p2 : true
|
||||
>true : true
|
||||
|
||||
p3: 42,
|
||||
>p3 : number
|
||||
>42 : 42
|
||||
|
||||
p4: "hello"
|
||||
>p4 : string
|
||||
>"hello" : "hello"
|
||||
|
||||
};
|
||||
|
||||
// This has excess error because variant two is the only applicable case
|
||||
const c: DisjointDiscriminants = {
|
||||
>c : DisjointDiscriminants
|
||||
>{ p1: 'right', p2: false, p3: 42, p4: "hello"} : { p1: "right"; p2: false; p3: number; p4: string; }
|
||||
|
||||
p1: 'right',
|
||||
>p1 : "right"
|
||||
>'right' : "right"
|
||||
|
||||
p2: false,
|
||||
>p2 : false
|
||||
>false : false
|
||||
|
||||
p3: 42,
|
||||
>p3 : number
|
||||
>42 : 42
|
||||
|
||||
p4: "hello"
|
||||
>p4 : string
|
||||
>"hello" : "hello"
|
||||
|
||||
};
|
||||
|
||||
@ -23,9 +23,11 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(50,35): error TS2322: Type
|
||||
tests/cases/compiler/excessPropertyCheckWithUnions.ts(66,9): error TS2326: Types of property 'n' are incompatible.
|
||||
Type '{ a: string; b: string; }' is not assignable to type 'AN'.
|
||||
Object literal may only specify known properties, and 'b' does not exist in type 'AN'.
|
||||
tests/cases/compiler/excessPropertyCheckWithUnions.ts(87,5): error TS2322: Type '{ tag: "button"; type: "submit"; href: string; }' is not assignable to type 'Union'.
|
||||
Object literal may only specify known properties, and 'href' does not exist in type 'Button'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (10 errors) ====
|
||||
==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (11 errors) ====
|
||||
type ADT = {
|
||||
tag: "A",
|
||||
a1: string
|
||||
@ -137,4 +139,20 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(66,9): error TS2326: Types
|
||||
c: "c", // ok -- kind: "A", an: { a: string } | { c: string }
|
||||
}
|
||||
}
|
||||
|
||||
// Excess property checks must match all discriminable properties
|
||||
type Button = { tag: 'button'; type?: 'submit'; };
|
||||
type Anchor = { tag: 'a'; type?: string; href: string };
|
||||
|
||||
type Union = Button | Anchor;
|
||||
const obj: Union = {
|
||||
tag: 'button',
|
||||
type: 'submit',
|
||||
|
||||
// should have error here
|
||||
href: 'foo',
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ tag: "button"; type: "submit"; href: string; }' is not assignable to type 'Union'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'href' does not exist in type 'Button'.
|
||||
};
|
||||
|
||||
@ -74,6 +74,19 @@ const abac: AB = {
|
||||
c: "c", // ok -- kind: "A", an: { a: string } | { c: string }
|
||||
}
|
||||
}
|
||||
|
||||
// Excess property checks must match all discriminable properties
|
||||
type Button = { tag: 'button'; type?: 'submit'; };
|
||||
type Anchor = { tag: 'a'; type?: string; href: string };
|
||||
|
||||
type Union = Button | Anchor;
|
||||
const obj: Union = {
|
||||
tag: 'button',
|
||||
type: 'submit',
|
||||
|
||||
// should have error here
|
||||
href: 'foo',
|
||||
};
|
||||
|
||||
|
||||
//// [excessPropertyCheckWithUnions.js]
|
||||
@ -125,3 +138,9 @@ var abac = {
|
||||
c: "c"
|
||||
}
|
||||
};
|
||||
var obj = {
|
||||
tag: 'button',
|
||||
type: 'submit',
|
||||
// should have error here
|
||||
href: 'foo'
|
||||
};
|
||||
|
||||
@ -221,3 +221,36 @@ const abac: AB = {
|
||||
}
|
||||
}
|
||||
|
||||
// Excess property checks must match all discriminable properties
|
||||
type Button = { tag: 'button'; type?: 'submit'; };
|
||||
>Button : Symbol(Button, Decl(excessPropertyCheckWithUnions.ts, 74, 1))
|
||||
>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 77, 15))
|
||||
>type : Symbol(type, Decl(excessPropertyCheckWithUnions.ts, 77, 30))
|
||||
|
||||
type Anchor = { tag: 'a'; type?: string; href: string };
|
||||
>Anchor : Symbol(Anchor, Decl(excessPropertyCheckWithUnions.ts, 77, 50))
|
||||
>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 78, 15))
|
||||
>type : Symbol(type, Decl(excessPropertyCheckWithUnions.ts, 78, 25))
|
||||
>href : Symbol(href, Decl(excessPropertyCheckWithUnions.ts, 78, 40))
|
||||
|
||||
type Union = Button | Anchor;
|
||||
>Union : Symbol(Union, Decl(excessPropertyCheckWithUnions.ts, 78, 56))
|
||||
>Button : Symbol(Button, Decl(excessPropertyCheckWithUnions.ts, 74, 1))
|
||||
>Anchor : Symbol(Anchor, Decl(excessPropertyCheckWithUnions.ts, 77, 50))
|
||||
|
||||
const obj: Union = {
|
||||
>obj : Symbol(obj, Decl(excessPropertyCheckWithUnions.ts, 81, 5))
|
||||
>Union : Symbol(Union, Decl(excessPropertyCheckWithUnions.ts, 78, 56))
|
||||
|
||||
tag: 'button',
|
||||
>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 81, 20))
|
||||
|
||||
type: 'submit',
|
||||
>type : Symbol(type, Decl(excessPropertyCheckWithUnions.ts, 82, 18))
|
||||
|
||||
// should have error here
|
||||
href: 'foo',
|
||||
>href : Symbol(href, Decl(excessPropertyCheckWithUnions.ts, 83, 19))
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -278,3 +278,37 @@ const abac: AB = {
|
||||
}
|
||||
}
|
||||
|
||||
// Excess property checks must match all discriminable properties
|
||||
type Button = { tag: 'button'; type?: 'submit'; };
|
||||
>Button : Button
|
||||
>tag : "button"
|
||||
>type : "submit" | undefined
|
||||
|
||||
type Anchor = { tag: 'a'; type?: string; href: string };
|
||||
>Anchor : Anchor
|
||||
>tag : "a"
|
||||
>type : string | undefined
|
||||
>href : string
|
||||
|
||||
type Union = Button | Anchor;
|
||||
>Union : Union
|
||||
|
||||
const obj: Union = {
|
||||
>obj : Union
|
||||
>{ tag: 'button', type: 'submit', // should have error here href: 'foo',} : { tag: "button"; type: "submit"; href: string; }
|
||||
|
||||
tag: 'button',
|
||||
>tag : "button"
|
||||
>'button' : "button"
|
||||
|
||||
type: 'submit',
|
||||
>type : "submit"
|
||||
>'submit' : "submit"
|
||||
|
||||
// should have error here
|
||||
href: 'foo',
|
||||
>href : string
|
||||
>'foo' : "foo"
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
// Repro from #32657
|
||||
|
||||
interface Base<T> {
|
||||
value: T;
|
||||
}
|
||||
|
||||
interface Int extends Base<number> {
|
||||
type: "integer";
|
||||
multipleOf?: number;
|
||||
}
|
||||
|
||||
interface Float extends Base<number> {
|
||||
type: "number";
|
||||
}
|
||||
|
||||
interface Str extends Base<string> {
|
||||
type: "string";
|
||||
format?: string;
|
||||
}
|
||||
|
||||
interface Bool extends Base<boolean> {
|
||||
type: "boolean";
|
||||
}
|
||||
|
||||
type Primitive = Int | Float | Str | Bool;
|
||||
|
||||
const foo: Primitive = {
|
||||
type: "number",
|
||||
value: 10,
|
||||
multipleOf: 5, // excess property
|
||||
format: "what?"
|
||||
}
|
||||
|
||||
|
||||
type DisjointDiscriminants = { p1: 'left'; p2: true; p3: number } | { p1: 'right'; p2: false; p4: string } | { p1: 'left'; p2: boolean };
|
||||
|
||||
// This has excess error because variant three is the only applicable case.
|
||||
const a: DisjointDiscriminants = {
|
||||
p1: 'left',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
// This has no excess error because variant one and three are both applicable.
|
||||
const b: DisjointDiscriminants = {
|
||||
p1: 'left',
|
||||
p2: true,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
|
||||
// This has excess error because variant two is the only applicable case
|
||||
const c: DisjointDiscriminants = {
|
||||
p1: 'right',
|
||||
p2: false,
|
||||
p3: 42,
|
||||
p4: "hello"
|
||||
};
|
||||
@ -74,3 +74,16 @@ const abac: AB = {
|
||||
c: "c", // ok -- kind: "A", an: { a: string } | { c: string }
|
||||
}
|
||||
}
|
||||
|
||||
// Excess property checks must match all discriminable properties
|
||||
type Button = { tag: 'button'; type?: 'submit'; };
|
||||
type Anchor = { tag: 'a'; type?: string; href: string };
|
||||
|
||||
type Union = Button | Anchor;
|
||||
const obj: Union = {
|
||||
tag: 'button',
|
||||
type: 'submit',
|
||||
|
||||
// should have error here
|
||||
href: 'foo',
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user