TypeScript实现根据首参数属性可选性条件要求第二参数的类型安全safeGet函数
问题根源
- 你调用
safeGet<Person>()时仅显式传入了泛型T的类型,剩余泛型K、V都会使用定义的默认值:K默认是keyof Person联合类型,V默认是Person[keyof Person]即string | number | undefined,此时判断V extends null | undefined的结果为false,剩余参数类型永远是空数组,因此无论传入什么key都不接受第二个参数。 - 原有泛型设计没有让TS根据第一个入参
key的实际值推导对应的K的精确类型,直接使用联合类型默认值导致条件类型判断失效。
正确实现
// 条件类型判断当前key是否需要传入默认值 type RequiredDefault<T, K extends keyof T> = undefined extends T[K] ? [NonNullable<T[K]>] : [] function safeGet<T, K extends keyof T>(key: K, ...defaultValue: RequiredDefault<T, K>) { return (obj: T) => { const val = obj[key] return val !== undefined ? val : defaultValue[0] } }
效果校验
完全符合你给出的预期行为:
interface Person { name: string totalKids?: number } // 可选属性场景 safeGet<Person>('totalKids') // 报错:预期2个参数,仅收到1个 safeGet<Person>('totalKids', 4) // 校验通过 safeGet<Person>('totalKids', 'four') // 报错:string类型不能分配给number类型 safeGet<Person>('totalKids', undefined) // 报错:undefined不能分配给number类型 // 必选属性场景 safeGet<Person>('name') // 校验通过 safeGet<Person>('name', 'John') // 报错:预期1个参数,收到2个
内容的提问来源于stack exchange,提问作者BernaMariano
相关产品推荐
相关产品推荐

