繁体   English   中英

如何在 Typescript 中映射函数的两个参数的类型?

[英]How to map types of two arguments of function in Typescript?

如何实现这样的功能?

type SomeType = {
  name: string;
  quantity: number;
};
const someFunc = (
  key: keyof SomeType /* what should be here?  */,
  value: SomeType[keyof SomeType] /* what should be here?  */
) => {
  // ...
};
someFunc("name", "John") // OK
someFunc("name", 10) // must be error
someFunc("quantity", "John") // must be error
someFunc("quantity", 10) // OK

我试过这个:

...
const someFunc = (
  key: keyof SomeType
  value: SomeType[keyof SomeType]
)
...

但这行不通,我明白为什么。 所以我不知道如何实现这个。

我认为没有 100% 万无一失的方法可以做到这一点。 您可以使用泛型类型参数关闭:

type SomeType = {
    name: string;
    quantity: number;
};
const someFunc = <Key extends keyof SomeType>(
    key: Key,
    value: SomeType[Key],
) => {
    // ...
};

这样,您的示例就可以工作了:

someFunc("name", "John") // OK
someFunc("name", 10) // Error as desired
someFunc("quantity", "John") // Error as desired
someFunc("quantity", 10) // OK

但是,由于工会,它不是 100%。 我们可以为类型参数指定一个显式类型参数,然后强制它采用错误的keyvalue组合:

someFunc<"name" | "quantity">("name", 10) // wrong, but no error

这对函数内部的代码有影响,因为您希望缩小key的类型以缩小value的类型,但事实并非如此; 看到这个问题的答案

对@TJ Crowder 解决方案的万无一失的改进并不是那么理想

它阻止您使用 union 但不检查值类型的正确性

type UnionToIntersection<U> =
    (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true

type SomeType = {
    name: string;
    quantity: number;
    age: number
};
const someFunc = <Key extends keyof SomeType>(
    key: IsUnion<Key> extends true ? "No Union!" : Key,
    value: SomeType[Key],
) => {
    // ...
};

someFunc<"name" | "quantity">("name", 10) //  error at argument 1, ideally should error at argument 2, but still an error regardless, a true negative case
someFunc<"quantity" | "age">("quantity", 10) //  should not error, because both quantity and age are number, a false negative case

// still works as normal
someFunc("name", "John") // OK
someFunc("name", 10) // Error as desired
someFunc("quantity", "John") // Error as desired
someFunc("quantity", 10) // OK

在此处输入图像描述 操场

是联盟

如代码所示,不仅在错误的参数上出错,还有一个假阴性的情况

但这有关系吗? 不,它没有

因为无论如何都必须通过删除联合来修复错误,所以清除假阴性案例不会导致另一种类型的错误

所以最终结果是,它仍然会引导您找到正确的类型

这不是一个理想的方法,但它是有效的,它是安全总比错误好

一个问题是这对新手不友好,需要研究背景问题才能理解代码为什么这样写,为什么错误出现在错误的参数上或无缘无故出现。

对于那些新手来说,每次都会以失败告终,而我们都知道,他们接下来要做的就是怀疑自己存在的意义

你不可能像你给一个 5 岁的孩子解释的那样,所以 TS 应该承担责任

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM