首页 > 解决方案 > 基于第一个参数要求有条件地需要第二个参数的 TypeScript 函数

问题描述

我想编写一个完全类型安全的get函数,该函数接受该属性作为第一个参数,可能还有一个默认值作为第二个参数,但前提是第一个参数的类型可以是未定义的。

例子:

interface Person {
  name: string
  totalKids?: number
}

// defaultValue as 2nd argument IS NECESSARY because "totalKids" could be undefined in Person
safeGet<Person>('totalKids') // Error: safeGet expected 2 arguments but got only 1.
safeGet<Person>('totalKids', 4) // OK
safeGet<Person>('totalKids', 'four') // Error: string is not assignable to number
safeGet<Person>('totalKids', undefined) // Error: undefined is not assignable to number

// defaultValue as 2nd argument is NOT necessary because "name" is always a string in Person
safeGet<Person>('name') // OK
safeGet<Person>('name', 'John') // Error: safeGet expected 1 argument but got 2.

请注意在最后一个totalKids示例 ( safeGet<Person>('totalKids', undefined)) 中,即使Person['totalKids']可以未定义,第二个参数defaultValue也排除了该选项。

我目前拥有的:

function safeGet<T, K extends keyof T = keyof T, V extends T[K] = T[K]>(
  key: K,
  ...defaultValue: V extends null | undefined ? [NonNullable<V>] : []
) {
  return (obj: T): V => {
    if (obj[key]) {
      return obj[key] as V
    }
    return defaultValue[0] as V
  }
}

但它从不期望第二个参数(总是never)

safeGet<Person>('name') // Compiles OK
safeGet<Person>('name', 'John') // Errors OK

safeGet<Person>('totalKids') // Compiles but should not
safeGet<Person>('totalKids', 'four') // Errors but not because of arg not expected (never)
safeGet<Person>('totalKids', 4) // Errors but should compile
safeGet<Person>('totalKids', undefined) // Errors but because of arg not expected (never)

我究竟做错了什么?

标签: typescript

解决方案


推荐阅读