mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
Filter primitives from union when checking for mismatched excess props if nonprimitive type is present (#31708)
* Filter primitives from union when checking for mismatched excess props if nonprimitive type is present * Use maybeTypeOfKind
This commit is contained in:
parent
a0d164f142
commit
74c6bc1f85
@ -12600,8 +12600,8 @@ namespace ts {
|
||||
result = typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive));
|
||||
if (result && isPerformingExcessPropertyChecks) {
|
||||
// Validate against excess props using the original `source`
|
||||
const discriminantType = target.flags & TypeFlags.Union ? findMatchingDiscriminantType(source, target as UnionType) : undefined;
|
||||
if (!propertiesRelatedTo(source, discriminantType || target, reportErrors, /*excludedProperties*/ undefined)) {
|
||||
const discriminantType = findMatchingDiscriminantType(source, target as UnionType) || filterPrimitivesIfContainsNonPrimitive(target as UnionType);
|
||||
if (!propertiesRelatedTo(source, discriminantType, reportErrors, /*excludedProperties*/ undefined)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
@ -12872,6 +12872,16 @@ namespace ts {
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
function filterPrimitivesIfContainsNonPrimitive(type: UnionType) {
|
||||
if (maybeTypeOfKind(type, TypeFlags.NonPrimitive)) {
|
||||
const result = filterType(type, t => !(t.flags & TypeFlags.Primitive));
|
||||
if (!(result.flags & TypeFlags.Never)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
|
||||
function findMatchingDiscriminantType(source: Type, target: Type) {
|
||||
if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) {
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
tests/cases/compiler/discriminateObjectTypesOnly.ts(9,7): error TS2741: Property 'toFixed' is missing in type '{ toString: undefined; }' but required in type '{ toFixed: null; toString: undefined; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/discriminateObjectTypesOnly.ts (1 errors) ====
|
||||
type Thing = number | object;
|
||||
const k: Thing = { toFixed: null }; // OK, satisfies object
|
||||
|
||||
type Thing2 = number | { toFixed: null } | object;
|
||||
const q: Thing2 = { toFixed: null };
|
||||
const h: Thing2 = { toString: null }; // OK, satisfies object
|
||||
|
||||
type Thing3 = number | { toFixed: null, toString: undefined } | object;
|
||||
const l: Thing3 = { toString: undefined }; // error, toFixed isn't null
|
||||
~
|
||||
!!! error TS2741: Property 'toFixed' is missing in type '{ toString: undefined; }' but required in type '{ toFixed: null; toString: undefined; }'.
|
||||
!!! related TS2728 tests/cases/compiler/discriminateObjectTypesOnly.ts:8:26: 'toFixed' is declared here.
|
||||
|
||||
18
tests/baselines/reference/discriminateObjectTypesOnly.js
Normal file
18
tests/baselines/reference/discriminateObjectTypesOnly.js
Normal file
@ -0,0 +1,18 @@
|
||||
//// [discriminateObjectTypesOnly.ts]
|
||||
type Thing = number | object;
|
||||
const k: Thing = { toFixed: null }; // OK, satisfies object
|
||||
|
||||
type Thing2 = number | { toFixed: null } | object;
|
||||
const q: Thing2 = { toFixed: null };
|
||||
const h: Thing2 = { toString: null }; // OK, satisfies object
|
||||
|
||||
type Thing3 = number | { toFixed: null, toString: undefined } | object;
|
||||
const l: Thing3 = { toString: undefined }; // error, toFixed isn't null
|
||||
|
||||
|
||||
//// [discriminateObjectTypesOnly.js]
|
||||
"use strict";
|
||||
var k = { toFixed: null }; // OK, satisfies object
|
||||
var q = { toFixed: null };
|
||||
var h = { toString: null }; // OK, satisfies object
|
||||
var l = { toString: undefined }; // error, toFixed isn't null
|
||||
@ -0,0 +1,34 @@
|
||||
=== tests/cases/compiler/discriminateObjectTypesOnly.ts ===
|
||||
type Thing = number | object;
|
||||
>Thing : Symbol(Thing, Decl(discriminateObjectTypesOnly.ts, 0, 0))
|
||||
|
||||
const k: Thing = { toFixed: null }; // OK, satisfies object
|
||||
>k : Symbol(k, Decl(discriminateObjectTypesOnly.ts, 1, 5))
|
||||
>Thing : Symbol(Thing, Decl(discriminateObjectTypesOnly.ts, 0, 0))
|
||||
>toFixed : Symbol(toFixed, Decl(discriminateObjectTypesOnly.ts, 1, 18))
|
||||
|
||||
type Thing2 = number | { toFixed: null } | object;
|
||||
>Thing2 : Symbol(Thing2, Decl(discriminateObjectTypesOnly.ts, 1, 35))
|
||||
>toFixed : Symbol(toFixed, Decl(discriminateObjectTypesOnly.ts, 3, 24))
|
||||
|
||||
const q: Thing2 = { toFixed: null };
|
||||
>q : Symbol(q, Decl(discriminateObjectTypesOnly.ts, 4, 5))
|
||||
>Thing2 : Symbol(Thing2, Decl(discriminateObjectTypesOnly.ts, 1, 35))
|
||||
>toFixed : Symbol(toFixed, Decl(discriminateObjectTypesOnly.ts, 4, 19))
|
||||
|
||||
const h: Thing2 = { toString: null }; // OK, satisfies object
|
||||
>h : Symbol(h, Decl(discriminateObjectTypesOnly.ts, 5, 5))
|
||||
>Thing2 : Symbol(Thing2, Decl(discriminateObjectTypesOnly.ts, 1, 35))
|
||||
>toString : Symbol(toString, Decl(discriminateObjectTypesOnly.ts, 5, 19))
|
||||
|
||||
type Thing3 = number | { toFixed: null, toString: undefined } | object;
|
||||
>Thing3 : Symbol(Thing3, Decl(discriminateObjectTypesOnly.ts, 5, 37))
|
||||
>toFixed : Symbol(toFixed, Decl(discriminateObjectTypesOnly.ts, 7, 24))
|
||||
>toString : Symbol(toString, Decl(discriminateObjectTypesOnly.ts, 7, 39))
|
||||
|
||||
const l: Thing3 = { toString: undefined }; // error, toFixed isn't null
|
||||
>l : Symbol(l, Decl(discriminateObjectTypesOnly.ts, 8, 5))
|
||||
>Thing3 : Symbol(Thing3, Decl(discriminateObjectTypesOnly.ts, 5, 37))
|
||||
>toString : Symbol(toString, Decl(discriminateObjectTypesOnly.ts, 8, 19))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
39
tests/baselines/reference/discriminateObjectTypesOnly.types
Normal file
39
tests/baselines/reference/discriminateObjectTypesOnly.types
Normal file
@ -0,0 +1,39 @@
|
||||
=== tests/cases/compiler/discriminateObjectTypesOnly.ts ===
|
||||
type Thing = number | object;
|
||||
>Thing : Thing
|
||||
|
||||
const k: Thing = { toFixed: null }; // OK, satisfies object
|
||||
>k : Thing
|
||||
>{ toFixed: null } : { toFixed: null; }
|
||||
>toFixed : null
|
||||
>null : null
|
||||
|
||||
type Thing2 = number | { toFixed: null } | object;
|
||||
>Thing2 : Thing2
|
||||
>toFixed : null
|
||||
>null : null
|
||||
|
||||
const q: Thing2 = { toFixed: null };
|
||||
>q : Thing2
|
||||
>{ toFixed: null } : { toFixed: null; }
|
||||
>toFixed : null
|
||||
>null : null
|
||||
|
||||
const h: Thing2 = { toString: null }; // OK, satisfies object
|
||||
>h : Thing2
|
||||
>{ toString: null } : { toString: null; }
|
||||
>toString : null
|
||||
>null : null
|
||||
|
||||
type Thing3 = number | { toFixed: null, toString: undefined } | object;
|
||||
>Thing3 : Thing3
|
||||
>toFixed : null
|
||||
>null : null
|
||||
>toString : undefined
|
||||
|
||||
const l: Thing3 = { toString: undefined }; // error, toFixed isn't null
|
||||
>l : Thing3
|
||||
>{ toString: undefined } : { toString: undefined; }
|
||||
>toString : undefined
|
||||
>undefined : undefined
|
||||
|
||||
10
tests/cases/compiler/discriminateObjectTypesOnly.ts
Normal file
10
tests/cases/compiler/discriminateObjectTypesOnly.ts
Normal file
@ -0,0 +1,10 @@
|
||||
// @strict: true
|
||||
type Thing = number | object;
|
||||
const k: Thing = { toFixed: null }; // OK, satisfies object
|
||||
|
||||
type Thing2 = number | { toFixed: null } | object;
|
||||
const q: Thing2 = { toFixed: null };
|
||||
const h: Thing2 = { toString: null }; // OK, satisfies object
|
||||
|
||||
type Thing3 = number | { toFixed: null, toString: undefined } | object;
|
||||
const l: Thing3 = { toString: undefined }; // error, toFixed isn't null
|
||||
Loading…
x
Reference in New Issue
Block a user