Fixed an issue with assignments to dynamic properties with `exactOptionalPropertyTypes`

This commit is contained in:
Mateusz Burzyński 2023-08-27 19:18:50 +02:00
Родитель 27a5bdd446
Коммит f6083db451
7 изменённых файлов: 294 добавлений и 1 удалений

Просмотреть файл

@ -32200,7 +32200,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// accessor, or optional method.
const assignmentKind = getAssignmentTargetKind(node);
if (assignmentKind === AssignmentKind.Definite) {
return removeMissingType(propType, !!(prop && prop.flags & SymbolFlags.Optional));
// since this is used as an assignment target we always want to remove the missing type
// usually this is done conditionally based on the `prop.flags`
// the prop might not be available here though if the assignment is done to a dynamic property
return removeMissingType(propType, /*isOptional*/ true);
}
if (
prop &&

Просмотреть файл

@ -0,0 +1,56 @@
//// [tests/cases/compiler/propertyAssignmentDynamicOptionalProp.ts] ////
=== propertyAssignmentDynamicOptionalProp.ts ===
// https://github.com/microsoft/TypeScript/issues/55526
type Something1 = {
>Something1 : Symbol(Something1, Decl(propertyAssignmentDynamicOptionalProp.ts, 0, 0))
a?: string;
>a : Symbol(a, Decl(propertyAssignmentDynamicOptionalProp.ts, 2, 19))
};
const x1: Something1 = {};
>x1 : Symbol(x1, Decl(propertyAssignmentDynamicOptionalProp.ts, 6, 5))
>Something1 : Symbol(Something1, Decl(propertyAssignmentDynamicOptionalProp.ts, 0, 0))
function assignToKey1(key: keyof Something1, value: string | undefined) {
>assignToKey1 : Symbol(assignToKey1, Decl(propertyAssignmentDynamicOptionalProp.ts, 6, 26))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 22))
>Something1 : Symbol(Something1, Decl(propertyAssignmentDynamicOptionalProp.ts, 0, 0))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 44))
x1[key] = value;
>x1 : Symbol(x1, Decl(propertyAssignmentDynamicOptionalProp.ts, 6, 5))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 22))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 44))
}
type Something2 = {
>Something2 : Symbol(Something2, Decl(propertyAssignmentDynamicOptionalProp.ts, 10, 1))
a?: string;
>a : Symbol(a, Decl(propertyAssignmentDynamicOptionalProp.ts, 12, 19))
b?: string;
>b : Symbol(b, Decl(propertyAssignmentDynamicOptionalProp.ts, 13, 13))
};
const x2: Something2 = {};
>x2 : Symbol(x2, Decl(propertyAssignmentDynamicOptionalProp.ts, 17, 5))
>Something2 : Symbol(Something2, Decl(propertyAssignmentDynamicOptionalProp.ts, 10, 1))
function assignToKey2(key: keyof Something2, value: string | undefined) {
>assignToKey2 : Symbol(assignToKey2, Decl(propertyAssignmentDynamicOptionalProp.ts, 17, 26))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 22))
>Something2 : Symbol(Something2, Decl(propertyAssignmentDynamicOptionalProp.ts, 10, 1))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 44))
x2[key] = value;
>x2 : Symbol(x2, Decl(propertyAssignmentDynamicOptionalProp.ts, 17, 5))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 22))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 44))
}

Просмотреть файл

@ -0,0 +1,58 @@
//// [tests/cases/compiler/propertyAssignmentDynamicOptionalProp.ts] ////
=== propertyAssignmentDynamicOptionalProp.ts ===
// https://github.com/microsoft/TypeScript/issues/55526
type Something1 = {
>Something1 : { a?: string | undefined; }
a?: string;
>a : string | undefined
};
const x1: Something1 = {};
>x1 : Something1
>{} : {}
function assignToKey1(key: keyof Something1, value: string | undefined) {
>assignToKey1 : (key: keyof Something1, value: string | undefined) => void
>key : "a"
>value : string | undefined
x1[key] = value;
>x1[key] = value : string | undefined
>x1[key] : string | undefined
>x1 : Something1
>key : "a"
>value : string | undefined
}
type Something2 = {
>Something2 : { a?: string | undefined; b?: string | undefined; }
a?: string;
>a : string | undefined
b?: string;
>b : string | undefined
};
const x2: Something2 = {};
>x2 : Something2
>{} : {}
function assignToKey2(key: keyof Something2, value: string | undefined) {
>assignToKey2 : (key: keyof Something2, value: string | undefined) => void
>key : keyof Something2
>value : string | undefined
x2[key] = value;
>x2[key] = value : string | undefined
>x2[key] : string | undefined
>x2 : Something2
>key : keyof Something2
>value : string | undefined
}

Просмотреть файл

@ -0,0 +1,36 @@
propertyAssignmentDynamicOptionalProp.ts(10,3): error TS2322: Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
propertyAssignmentDynamicOptionalProp.ts(21,3): error TS2322: Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
==== propertyAssignmentDynamicOptionalProp.ts (2 errors) ====
// https://github.com/microsoft/TypeScript/issues/55526
type Something1 = {
a?: string;
};
const x1: Something1 = {};
function assignToKey1(key: keyof Something1, value: string | undefined) {
x1[key] = value;
~~~~~~~
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string'.
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
}
type Something2 = {
a?: string;
b?: string;
};
const x2: Something2 = {};
function assignToKey2(key: keyof Something2, value: string | undefined) {
x2[key] = value;
~~~~~~~
!!! error TS2322: Type 'string | undefined' is not assignable to type 'string'.
!!! error TS2322: Type 'undefined' is not assignable to type 'string'.
}

Просмотреть файл

@ -0,0 +1,56 @@
//// [tests/cases/compiler/propertyAssignmentDynamicOptionalProp.ts] ////
=== propertyAssignmentDynamicOptionalProp.ts ===
// https://github.com/microsoft/TypeScript/issues/55526
type Something1 = {
>Something1 : Symbol(Something1, Decl(propertyAssignmentDynamicOptionalProp.ts, 0, 0))
a?: string;
>a : Symbol(a, Decl(propertyAssignmentDynamicOptionalProp.ts, 2, 19))
};
const x1: Something1 = {};
>x1 : Symbol(x1, Decl(propertyAssignmentDynamicOptionalProp.ts, 6, 5))
>Something1 : Symbol(Something1, Decl(propertyAssignmentDynamicOptionalProp.ts, 0, 0))
function assignToKey1(key: keyof Something1, value: string | undefined) {
>assignToKey1 : Symbol(assignToKey1, Decl(propertyAssignmentDynamicOptionalProp.ts, 6, 26))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 22))
>Something1 : Symbol(Something1, Decl(propertyAssignmentDynamicOptionalProp.ts, 0, 0))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 44))
x1[key] = value;
>x1 : Symbol(x1, Decl(propertyAssignmentDynamicOptionalProp.ts, 6, 5))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 22))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 8, 44))
}
type Something2 = {
>Something2 : Symbol(Something2, Decl(propertyAssignmentDynamicOptionalProp.ts, 10, 1))
a?: string;
>a : Symbol(a, Decl(propertyAssignmentDynamicOptionalProp.ts, 12, 19))
b?: string;
>b : Symbol(b, Decl(propertyAssignmentDynamicOptionalProp.ts, 13, 13))
};
const x2: Something2 = {};
>x2 : Symbol(x2, Decl(propertyAssignmentDynamicOptionalProp.ts, 17, 5))
>Something2 : Symbol(Something2, Decl(propertyAssignmentDynamicOptionalProp.ts, 10, 1))
function assignToKey2(key: keyof Something2, value: string | undefined) {
>assignToKey2 : Symbol(assignToKey2, Decl(propertyAssignmentDynamicOptionalProp.ts, 17, 26))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 22))
>Something2 : Symbol(Something2, Decl(propertyAssignmentDynamicOptionalProp.ts, 10, 1))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 44))
x2[key] = value;
>x2 : Symbol(x2, Decl(propertyAssignmentDynamicOptionalProp.ts, 17, 5))
>key : Symbol(key, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 22))
>value : Symbol(value, Decl(propertyAssignmentDynamicOptionalProp.ts, 19, 44))
}

Просмотреть файл

@ -0,0 +1,58 @@
//// [tests/cases/compiler/propertyAssignmentDynamicOptionalProp.ts] ////
=== propertyAssignmentDynamicOptionalProp.ts ===
// https://github.com/microsoft/TypeScript/issues/55526
type Something1 = {
>Something1 : { a?: string; }
a?: string;
>a : string | undefined
};
const x1: Something1 = {};
>x1 : Something1
>{} : {}
function assignToKey1(key: keyof Something1, value: string | undefined) {
>assignToKey1 : (key: keyof Something1, value: string | undefined) => void
>key : "a"
>value : string | undefined
x1[key] = value;
>x1[key] = value : string | undefined
>x1[key] : string
>x1 : Something1
>key : "a"
>value : string | undefined
}
type Something2 = {
>Something2 : { a?: string; b?: string; }
a?: string;
>a : string | undefined
b?: string;
>b : string | undefined
};
const x2: Something2 = {};
>x2 : Something2
>{} : {}
function assignToKey2(key: keyof Something2, value: string | undefined) {
>assignToKey2 : (key: keyof Something2, value: string | undefined) => void
>key : keyof Something2
>value : string | undefined
x2[key] = value;
>x2[key] = value : string | undefined
>x2[key] : string
>x2 : Something2
>key : keyof Something2
>value : string | undefined
}

Просмотреть файл

@ -0,0 +1,26 @@
// @strict: true
// @exactOptionalPropertyTypes: true, false
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/55526
type Something1 = {
a?: string;
};
const x1: Something1 = {};
function assignToKey1(key: keyof Something1, value: string | undefined) {
x1[key] = value;
}
type Something2 = {
a?: string;
b?: string;
};
const x2: Something2 = {};
function assignToKey2(key: keyof Something2, value: string | undefined) {
x2[key] = value;
}