PartialsByKeys
介绍
实现一个通用的PartialByKeys<T, K>
,它接收两个类型参数T
和K
。
K
指定应设置为可选的T
的属性集。当没有提供K
时,它就和普通的Partial<T>
一样使所有属性都是可选的。
例如:
ts
interface User {name: stringage: numberaddress: string}type UserPartialName = PartialByKeys<User, 'name'> // { name?:string; age:number; address:string }
View on GitHubts
interface User {name: stringage: numberaddress: string}type UserPartialName = PartialByKeys<User, 'name'> // { name?:string; age:number; address:string }
起点
ts
/* _____________ Your Code Here _____________ */typePartialByKeys <T ,K > = any/* _____________ Test Cases _____________ */interfaceUser {name : stringage : numberaddress : string}interfaceUserPartialName {name ?: stringage : numberaddress : string}interfaceUserPartialNameAndAge {name ?: stringage ?: numberaddress : string}typecases = [Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.Expect <Equal <PartialByKeys <User , 'name'>,UserPartialName >>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.Expect <Equal <PartialByKeys <User , 'name' | 'age'>,UserPartialNameAndAge >>,Type 'false' does not satisfy the constraint 'true'.Expect <Equal <PartialByKeys <User >,Partial <User >>>,
Generic type 'PartialByKeys' requires 2 type argument(s).2344
2314Type 'false' does not satisfy the constraint 'true'.
Generic type 'PartialByKeys' requires 2 type argument(s).// @ts-expect-errorExpect <Equal <PartialByKeys <User , 'name' | 'unknown'>,UserPartialName >>,]
take the challengets
/* _____________ Your Code Here _____________ */typePartialByKeys <T ,K > = any/* _____________ Test Cases _____________ */interfaceUser {name : stringage : numberaddress : string}interfaceUserPartialName {name ?: stringage : numberaddress : string}interfaceUserPartialNameAndAge {name ?: stringage ?: numberaddress : string}typecases = [Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.Expect <Equal <PartialByKeys <User , 'name'>,UserPartialName >>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.Expect <Equal <PartialByKeys <User , 'name' | 'age'>,UserPartialNameAndAge >>,Type 'false' does not satisfy the constraint 'true'.Expect <Equal <PartialByKeys <User >,Partial <User >>>,
Generic type 'PartialByKeys' requires 2 type argument(s).2344
2314Type 'false' does not satisfy the constraint 'true'.
Generic type 'PartialByKeys' requires 2 type argument(s).// @ts-expect-errorExpect <Equal <PartialByKeys <User , 'name' | 'unknown'>,UserPartialName >>,]
解决方案
Spoiler warning // Click to reveal answer
ts
typePartialByKeys <T ,K = never> = {[P in keyofT asP extendsK ?P : never]?:T [P ]} & {[P in keyofT asP extendsK ? never :P ]:T [P ]}/*** 存在的问题: 可选属性的结果会是一个联合类型: 例如, name?: string | undefined* under strictNullChecks, TypeScript will tell us they’re potentially undefined.* 所以, 我们需要解决undefined的问题. 所以下文中IntersectionToObj的作用是?*/
ts
typePartialByKeys <T ,K = never> = {[P in keyofT asP extendsK ?P : never]?:T [P ]} & {[P in keyofT asP extendsK ? never :P ]:T [P ]}/*** 存在的问题: 可选属性的结果会是一个联合类型: 例如, name?: string | undefined* under strictNullChecks, TypeScript will tell us they’re potentially undefined.* 所以, 我们需要解决undefined的问题. 所以下文中IntersectionToObj的作用是?*/
ts
// most populartypePartialByKeys <T extends {},U = keyofT > =Omit <Partial <Pick <T ,U & keyofT >> &Omit <T ,U & keyofT >, never>;
ts
// most populartypePartialByKeys <T extends {},U = keyofT > =Omit <Partial <Pick <T ,U & keyofT >> &Omit <T ,U & keyofT >, never>;
ts
// most populartypeIntersectionToObj <T > = {[K in keyofT ]:T [K ]}typePartialByKeys <T ,K = any> =IntersectionToObj <{[P in keyofT asP extendsK ?P : never]?:T [P ]} & {[P inExclude <keyofT ,K >]:T [P ]}>
ts
// most populartypeIntersectionToObj <T > = {[K in keyofT ]:T [K ]}typePartialByKeys <T ,K = any> =IntersectionToObj <{[P in keyofT asP extendsK ?P : never]?:T [P ]} & {[P inExclude <keyofT ,K >]:T [P ]}>
ts
// deepseektypePartialByKeys <T ,K extends keyofT = keyofT > =Omit <T ,K > &Partial <Pick <T ,K >> extends inferO ? {[P in keyofO ]:O [P ]}: never;
ts
// deepseektypePartialByKeys <T ,K extends keyofT = keyofT > =Omit <T ,K > &Partial <Pick <T ,K >> extends inferO ? {[P in keyofO ]:O [P ]}: never;