From 400df445fee286cdedf5b1372ae6526b12768f4b Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:02:14 +0530 Subject: [PATCH 1/8] fix: set-optional with any --- source/set-optional.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/set-optional.d.ts b/source/set-optional.d.ts index 224004dcf..3b80a013d 100644 --- a/source/set-optional.d.ts +++ b/source/set-optional.d.ts @@ -31,5 +31,5 @@ export type SetOptional = // Pick just the keys that are readonly from the base type. Except & // Pick the keys that should be mutable from the base type and make them mutable. - Partial> + Partial>> >; From e7b4d096d65d7fc19cc9d3714cdde3b3b015e866 Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:02:58 +0530 Subject: [PATCH 2/8] test: more cases for set-optional --- test-d/set-optional.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test-d/set-optional.ts b/test-d/set-optional.ts index 649b4ec07..09d98cb25 100644 --- a/test-d/set-optional.ts +++ b/test-d/set-optional.ts @@ -16,3 +16,15 @@ expectType<{a?: number; b?: string; c?: boolean}>(variation3); // Fail if type changes even if optional is right. declare const variation4: SetOptional<{a: number; b?: string; c: boolean}, 'b' | 'c'>; expectNotAssignable<{a: boolean; b?: string; c?: boolean}>(variation4); + +// Preserves readonly modifier. +declare const variation5: SetOptional<{readonly a: number; readonly b?: string; c: boolean}, 'b' | 'c'>; +expectType<{readonly a: number; readonly b?: string; c?: boolean}>(variation5); + +// Marks all keys as optional, if `Keys` is `any`. +declare const variation6: SetOptional<{a: number; b: string; c: boolean}, any>; +expectType<{a?: number; b?: string; c?: boolean}>(variation6); + +// Does nothing, if `Keys` is `never`. +declare const variation7: SetOptional<{a?: number; readonly b?: string; readonly c: boolean}, never>; +expectType<{a?: number; readonly b?: string; readonly c: boolean}>(variation7); From 51c3882634463925720bf8545acd7a6619452264 Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:10:47 +0530 Subject: [PATCH 3/8] fix: set-required with any --- source/set-required.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/set-required.d.ts b/source/set-required.d.ts index 735c227c4..d7b00f4bb 100644 --- a/source/set-required.d.ts +++ b/source/set-required.d.ts @@ -35,6 +35,6 @@ export type SetRequired = // Pick just the keys that are optional from the base type. Except & // Pick the keys that should be required from the base type and make them required. - Required> + Required>> > : never; From 0f025e408aea8bb663c834732a8109aeed3c5d60 Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:11:12 +0530 Subject: [PATCH 4/8] test: more cases for set-required --- test-d/set-required.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test-d/set-required.ts b/test-d/set-required.ts index 4094e9cc9..6e51f0333 100644 --- a/test-d/set-required.ts +++ b/test-d/set-required.ts @@ -20,3 +20,19 @@ expectNotAssignable<{a?: boolean; b: string; c: boolean}>(variation4); // Update one required and one optional to required in a union. declare const variation5: SetRequired<{a?: '1'; b: string; c?: boolean} | {a?: '2'; b: string; c?: boolean}, 'a' | 'b'>; expectType<{a: '1'; b: string; c?: boolean} | {a: '2'; b: string; c?: boolean}>(variation5); + +// Preserves readonly modifier. +declare const variation6: SetRequired<{readonly a?: number; readonly b: string; c?: boolean}, 'b' | 'c'>; +expectType<{readonly a?: number; readonly b: string; c: boolean}>(variation6); + +// Works with unions. +declare const variation7: SetRequired<{readonly a?: number; b?: number; c?: boolean} | {a?: string; readonly b?: string; d?: boolean}, 'a' | 'b'>; +expectType<{readonly a: number; b: number; c?: boolean} | {a: string; readonly b: string; d?: boolean}>(variation7); + +// Marks all keys as required, if `Keys` is `any`. +declare const variation8: SetRequired<{readonly a?: number; b?: string; c?: boolean}, any>; +expectType<{readonly a: number; b: string; c: boolean}>(variation8); + +// Does nothing, if `Keys` is `never`. +declare const variation9: SetRequired<{a?: number; readonly b?: string; readonly c: boolean}, never>; +expectType<{a?: number; readonly b?: string; readonly c: boolean}>(variation9); From cdb3a45877c615a82d0d9f1c5f1a4b21fc3e8a5b Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:19:34 +0530 Subject: [PATCH 5/8] fix: set-optional with union --- source/set-optional.d.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source/set-optional.d.ts b/source/set-optional.d.ts index 3b80a013d..f2cfa9107 100644 --- a/source/set-optional.d.ts +++ b/source/set-optional.d.ts @@ -27,9 +27,11 @@ type SomeOptional = SetOptional; @category Object */ export type SetOptional = - Simplify< - // Pick just the keys that are readonly from the base type. - Except & - // Pick the keys that should be mutable from the base type and make them mutable. - Partial>> - >; + BaseType extends unknown // To distribute `BaseType` when it's a union type. + ? Simplify< + // Pick just the keys that are readonly from the base type. + Except & + // Pick the keys that should be mutable from the base type and make them mutable. + Partial>> + > + : never; From 885511044b66461944f02737e72a0188b5371695 Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:19:59 +0530 Subject: [PATCH 6/8] test: more cases for set-optional --- test-d/set-optional.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test-d/set-optional.ts b/test-d/set-optional.ts index 09d98cb25..aa7f8d1ac 100644 --- a/test-d/set-optional.ts +++ b/test-d/set-optional.ts @@ -21,10 +21,14 @@ expectNotAssignable<{a: boolean; b?: string; c?: boolean}>(variation4); declare const variation5: SetOptional<{readonly a: number; readonly b?: string; c: boolean}, 'b' | 'c'>; expectType<{readonly a: number; readonly b?: string; c?: boolean}>(variation5); +// Works with unions. +declare const variation6: SetOptional<{readonly a: number; b: number; c: boolean} | {a: string; readonly b: string; d: boolean}, 'a' | 'b'>; +expectType<{readonly a?: number; b?: number; c: boolean} | {a?: string; readonly b?: string; d: boolean}>(variation6); + // Marks all keys as optional, if `Keys` is `any`. -declare const variation6: SetOptional<{a: number; b: string; c: boolean}, any>; -expectType<{a?: number; b?: string; c?: boolean}>(variation6); +declare const variation7: SetOptional<{readonly a: number; b: string; c: boolean}, any>; +expectType<{readonly a?: number; b?: string; c?: boolean}>(variation7); // Does nothing, if `Keys` is `never`. -declare const variation7: SetOptional<{a?: number; readonly b?: string; readonly c: boolean}, never>; -expectType<{a?: number; readonly b?: string; readonly c: boolean}>(variation7); +declare const variation8: SetOptional<{a?: number; readonly b?: string; readonly c: boolean}, never>; +expectType<{a?: number; readonly b?: string; readonly c: boolean}>(variation8); From ab8df8de0dd2256375d506ccde265b912f4e4fae Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:31:05 +0530 Subject: [PATCH 7/8] fix: set-readonly with any --- source/set-readonly.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/set-readonly.d.ts b/source/set-readonly.d.ts index f8f4aa90c..bb6b19084 100644 --- a/source/set-readonly.d.ts +++ b/source/set-readonly.d.ts @@ -33,6 +33,6 @@ export type SetReadonly = BaseType extends unknown ? Simplify< Except & - Readonly> + Readonly>> > : never; From c5ce5c9f5d6e8c1f242c2b8cc94ba7021b584702 Mon Sep 17 00:00:00 2001 From: Som Shekhar Mukherjee Date: Sun, 15 Dec 2024 16:32:00 +0530 Subject: [PATCH 8/8] test: more cases for set-readonly --- test-d/set-readonly.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test-d/set-readonly.ts b/test-d/set-readonly.ts index d3d7dcf01..0ba0b9884 100644 --- a/test-d/set-readonly.ts +++ b/test-d/set-readonly.ts @@ -16,3 +16,19 @@ expectType<{readonly a: number; readonly b?: string; readonly c: boolean}>(varia // Fail if type changes even if readonly is right. declare const variation4: SetReadonly<{a: number; readonly b: string; c: boolean}, 'b' | 'c'>; expectNotAssignable<{a: boolean; readonly b: string; readonly c: boolean}>(variation4); + +// Preserves optional modifier. +declare const variation5: SetReadonly<{a?: number; readonly b?: string; c?: boolean}, 'b' | 'c'>; +expectType<{a?: number; readonly b?: string; readonly c?: boolean}>(variation5); + +// Works with unions. +declare const variation6: SetReadonly<{a?: number; b: number; c: boolean} | {a: string; b?: string; d: boolean}, 'a' | 'b'>; +expectType<{readonly a?: number; readonly b: number; c: boolean} | {readonly a: string; readonly b?: string; d: boolean}>(variation6); + +// Marks all keys as readonly, if `Keys` is `any`. +declare const variation7: SetReadonly<{a?: number; b: string; c: boolean}, any>; +expectType<{readonly a?: number; readonly b: string; readonly c: boolean}>(variation7); + +// Does nothing, if `Keys` is `never`. +declare const variation8: SetReadonly<{a: number; readonly b: string; readonly c: boolean}, never>; +expectType<{a: number; readonly b: string; readonly c: boolean}>(variation8);