Remove undefined from optional spread properties
Fixes #16509 by making the change from #15938 less strict. This is technically a hole, but it's not as big a hole as before #15938.
This commit is contained in:
parent
fbe002a595
commit
657c469d4f
|
@ -7716,7 +7716,7 @@ namespace ts {
|
||||||
const declarations: Declaration[] = concatenate(leftProp.declarations, rightProp.declarations);
|
const declarations: Declaration[] = concatenate(leftProp.declarations, rightProp.declarations);
|
||||||
const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional);
|
const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional);
|
||||||
const result = createSymbol(flags, leftProp.name);
|
const result = createSymbol(flags, leftProp.name);
|
||||||
result.type = getUnionType([getTypeOfSymbol(leftProp), rightType]);
|
result.type = getUnionType([getTypeOfSymbol(leftProp), getTypeWithFacts(rightType, TypeFacts.NEUndefined)]);
|
||||||
result.leftSpread = leftProp;
|
result.leftSpread = leftProp;
|
||||||
result.rightSpread = rightProp;
|
result.rightSpread = rightProp;
|
||||||
result.declarations = declarations;
|
result.declarations = declarations;
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(9,9): error TS2322: Type '{ sn: string | number | undefined; }' is not assignable to type '{ sn: string | number; }'.
|
|
||||||
Types of property 'sn' are incompatible.
|
|
||||||
Type 'string | number | undefined' is not assignable to type 'string | number'.
|
|
||||||
Type 'undefined' is not assignable to type 'string | number'.
|
|
||||||
tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(10,9): error TS2322: Type '{ sn: string | number | undefined; }' is not assignable to type '{ sn: string | number; }'.
|
|
||||||
Types of property 'sn' are incompatible.
|
|
||||||
Type 'string | number | undefined' is not assignable to type 'string | number'.
|
|
||||||
Type 'undefined' is not assignable to type 'string | number'.
|
|
||||||
tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(14,9): error TS2322: Type '{ sn: number | undefined; }' is not assignable to type '{ sn: string | number; }'.
|
tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(14,9): error TS2322: Type '{ sn: number | undefined; }' is not assignable to type '{ sn: string | number; }'.
|
||||||
Types of property 'sn' are incompatible.
|
Types of property 'sn' are incompatible.
|
||||||
Type 'number | undefined' is not assignable to type 'string | number'.
|
Type 'number | undefined' is not assignable to type 'string | number'.
|
||||||
|
@ -21,9 +13,13 @@ tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(18,9): error TS23
|
||||||
tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(28,7): error TS2322: Type '{ title: undefined; yearReleased: number; }' is not assignable to type 'Movie'.
|
tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(28,7): error TS2322: Type '{ title: undefined; yearReleased: number; }' is not assignable to type 'Movie'.
|
||||||
Types of property 'title' are incompatible.
|
Types of property 'title' are incompatible.
|
||||||
Type 'undefined' is not assignable to type 'string'.
|
Type 'undefined' is not assignable to type 'string'.
|
||||||
|
tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(42,5): error TS2322: Type '{ foo: number | undefined; bar: string | undefined; }' is not assignable to type 'Fields'.
|
||||||
|
Types of property 'foo' are incompatible.
|
||||||
|
Type 'number | undefined' is not assignable to type 'number'.
|
||||||
|
Type 'undefined' is not assignable to type 'number'.
|
||||||
|
|
||||||
|
|
||||||
==== tests/cases/conformance/types/spread/objectSpreadStrictNull.ts (6 errors) ====
|
==== tests/cases/conformance/types/spread/objectSpreadStrictNull.ts (5 errors) ====
|
||||||
function f(
|
function f(
|
||||||
definiteBoolean: { sn: boolean },
|
definiteBoolean: { sn: boolean },
|
||||||
definiteString: { sn: string },
|
definiteString: { sn: string },
|
||||||
|
@ -33,17 +29,7 @@ tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(28,7): error TS23
|
||||||
undefinedNumber: { sn: number | undefined }) {
|
undefinedNumber: { sn: number | undefined }) {
|
||||||
// optional
|
// optional
|
||||||
let optionalUnionStops: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalNumber };
|
let optionalUnionStops: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalNumber };
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2322: Type '{ sn: string | number | undefined; }' is not assignable to type '{ sn: string | number; }'.
|
|
||||||
!!! error TS2322: Types of property 'sn' are incompatible.
|
|
||||||
!!! error TS2322: Type 'string | number | undefined' is not assignable to type 'string | number'.
|
|
||||||
!!! error TS2322: Type 'undefined' is not assignable to type 'string | number'.
|
|
||||||
let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber };
|
let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber };
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2322: Type '{ sn: string | number | undefined; }' is not assignable to type '{ sn: string | number; }'.
|
|
||||||
!!! error TS2322: Types of property 'sn' are incompatible.
|
|
||||||
!!! error TS2322: Type 'string | number | undefined' is not assignable to type 'string | number'.
|
|
||||||
!!! error TS2322: Type 'undefined' is not assignable to type 'string | number'.
|
|
||||||
let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber };
|
let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber };
|
||||||
|
|
||||||
// undefined
|
// undefined
|
||||||
|
@ -82,3 +68,23 @@ tests/cases/conformance/types/spread/objectSpreadStrictNull.ts(28,7): error TS23
|
||||||
!!! error TS2322: Types of property 'title' are incompatible.
|
!!! error TS2322: Types of property 'title' are incompatible.
|
||||||
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
|
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
|
||||||
|
|
||||||
|
interface Fields {
|
||||||
|
foo: number;
|
||||||
|
bar: string;
|
||||||
|
}
|
||||||
|
interface NearlyPartialFields {
|
||||||
|
foo: number | undefined;
|
||||||
|
bar: string | undefined;
|
||||||
|
}
|
||||||
|
function g(fields: Fields, partialFields: Partial<Fields>, nearlyPartialFields: NearlyPartialFields) {
|
||||||
|
// ok, undefined is stripped from optional properties when spread
|
||||||
|
fields = { ...fields, ...partialFields };
|
||||||
|
// error: not optional, undefined remains
|
||||||
|
fields = { ...fields, ...nearlyPartialFields };
|
||||||
|
~~~~~~
|
||||||
|
!!! error TS2322: Type '{ foo: number | undefined; bar: string | undefined; }' is not assignable to type 'Fields'.
|
||||||
|
!!! error TS2322: Types of property 'foo' are incompatible.
|
||||||
|
!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'.
|
||||||
|
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,21 @@ const m = { title: "The Matrix", yearReleased: 1999 };
|
||||||
// should error here because title: undefined is not assignable to string
|
// should error here because title: undefined is not assignable to string
|
||||||
const x: Movie = { ...m, title: undefined };
|
const x: Movie = { ...m, title: undefined };
|
||||||
|
|
||||||
|
interface Fields {
|
||||||
|
foo: number;
|
||||||
|
bar: string;
|
||||||
|
}
|
||||||
|
interface NearlyPartialFields {
|
||||||
|
foo: number | undefined;
|
||||||
|
bar: string | undefined;
|
||||||
|
}
|
||||||
|
function g(fields: Fields, partialFields: Partial<Fields>, nearlyPartialFields: NearlyPartialFields) {
|
||||||
|
// ok, undefined is stripped from optional properties when spread
|
||||||
|
fields = { ...fields, ...partialFields };
|
||||||
|
// error: not optional, undefined remains
|
||||||
|
fields = { ...fields, ...nearlyPartialFields };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//// [objectSpreadStrictNull.js]
|
//// [objectSpreadStrictNull.js]
|
||||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||||
|
@ -52,3 +67,9 @@ function f(definiteBoolean, definiteString, optionalString, optionalNumber, unde
|
||||||
var m = { title: "The Matrix", yearReleased: 1999 };
|
var m = { title: "The Matrix", yearReleased: 1999 };
|
||||||
// should error here because title: undefined is not assignable to string
|
// should error here because title: undefined is not assignable to string
|
||||||
var x = __assign({}, m, { title: undefined });
|
var x = __assign({}, m, { title: undefined });
|
||||||
|
function g(fields, partialFields, nearlyPartialFields) {
|
||||||
|
// ok, undefined is stripped from optional properties when spread
|
||||||
|
fields = __assign({}, fields, partialFields);
|
||||||
|
// error: not optional, undefined remains
|
||||||
|
fields = __assign({}, fields, nearlyPartialFields);
|
||||||
|
}
|
||||||
|
|
|
@ -28,3 +28,18 @@ type Movie = {
|
||||||
const m = { title: "The Matrix", yearReleased: 1999 };
|
const m = { title: "The Matrix", yearReleased: 1999 };
|
||||||
// should error here because title: undefined is not assignable to string
|
// should error here because title: undefined is not assignable to string
|
||||||
const x: Movie = { ...m, title: undefined };
|
const x: Movie = { ...m, title: undefined };
|
||||||
|
|
||||||
|
interface Fields {
|
||||||
|
foo: number;
|
||||||
|
bar: string;
|
||||||
|
}
|
||||||
|
interface NearlyPartialFields {
|
||||||
|
foo: number | undefined;
|
||||||
|
bar: string | undefined;
|
||||||
|
}
|
||||||
|
function g(fields: Fields, partialFields: Partial<Fields>, nearlyPartialFields: NearlyPartialFields) {
|
||||||
|
// ok, undefined is stripped from optional properties when spread
|
||||||
|
fields = { ...fields, ...partialFields };
|
||||||
|
// error: not optional, undefined remains
|
||||||
|
fields = { ...fields, ...nearlyPartialFields };
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue