【问题标题】:How to typescript strictly typed conditional function?如何打字严格类型的条件函数?
【发布时间】:2021-06-25 12:21:14
【问题描述】:

我正在寻找一个真正的 Typescript 书呆子来帮助我解决这个问题。 我正在尝试创建一个带有两个参数的函数; key 为接口的键,value 为接口上该键的类型值。为了限制类型,我想将键作为条件类型传递,因此该函数不允许我引入类型与接口上该键定义的类型不同的值。这是该方法的一个示例:

interface A {
    a: number;
    b: string;
    c: boolean;
}

function Test<T extends keyof A> (key: T, value: Pick<A, T>){

    return;

}
/* Expected results */

const res = Test<'a'>('a', 1) //ok
const res = Test<'a'>('a', true) //wrong
const res = Test<'d'>('d', true) //wrong
const res = Test<''>('', true) //display autocompletion of possible values (keys of A)

我正在寻找这些东西:

  1. 可用键值的自动完成
  2. 如果我设置的值的类型与接口 A 中为该键定义的类型不同,该函数会对我大喊大叫

如果其他方法与此方法一样严格,我接受。

问候

【问题讨论】:

  • function Test&lt;T extends keyof A&gt;(key: T, value: A[T])
  • 如果你想自动完成,不要使用类型转换 - 你不需要类型转换 - 将推断通用参数

标签: typescript typescript-typings


【解决方案1】:

@CameronLittle 描述的泛型将满足您的需求。 If 将根据提供的字符串推断键的类型,并强制值与该键匹配。

但是,由于您要求“真正的 Typescript 书呆子”,我不得不指出,技术上如果您自己设置泛型而不是让它被推断,您可以传递无效的参数。例如:

const res = Test<keyof A>('a', true);

这不是错误,因为'a' 可分配给keyof A,而true 可分配给A[keyof A]。理想情况下,我们希望这是一个错误,因为 true 不能分配给 A['a']

最安全的方法是使用有效配对的联合而不是泛型。

type Args = {
    [K in keyof A]: [K, A[K]];
}[keyof A]

上述映射类型解析为联合:

type Args = ["a", number] | ["b", string] | ["c", boolean]

这些元组是我们希望Test 接受的参数。

function Test(...args: Args): void {};

这为我们提供了正确的类型检查,并消除了我们可以无效调用它的可能性。

const res1 = Test('a', 1) //ok
const res2 = Test('a', true) //wrong
const res3 = Test('d', true) //wrong
const res4 = Test('c', true) //ok

Typescript Playground Link

【讨论】:

    【解决方案2】:

    尝试使用A[T] 而不是Pick&lt;A, T&gt;

    interface A {
        a: number;
        b: string;
        c_more_to_show_autocomplete: boolean;
    }
    
    declare function Test<T extends keyof A>(key: T, value: A[T]): void;
    
    const res = Test('a', 1) //ok
    const res = Test('a', true) //wrong
    const res = Test('d', true) //wrong
    const res = Test('c_', true) //display autocompletion of possible values (keys of A)
    

    TypeScript playground

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 2021-09-17
      • 2022-07-07
      • 1970-01-01
      • 2023-03-24
      • 2019-09-02
      • 1970-01-01
      相关资源
      最近更新 更多