gpt4 book ai didi

arrays - TypeScript - 从对象数组中的键获取函数参数

转载 作者:行者123 更新时间:2023-12-04 11:48:10 29 4
gpt4 key购买 nike

我正在尝试编写一个函数,该函数将数组中特定对象的两个键作为参数。 key 如下:

  • 用于索引特定对象的字符串
  • 一个函数(我需要它的参数类型)

  • 对象数组如下
    const obj = [
    {
    name: "number",
    func: (foo: number) => foo,
    },
    {
    name: "string",
    func: (foo: string) => foo,
    },
    {
    name: "array",
    func: (foo: string[]) => foo,
    },
    ];

    这是我的方法
    type SingleObject = typeof obj[number];
    type Name<T extends SingleObject> = T["name"];
    type FuncParams<T extends SingleObject> = Parameters<T["func"]>;

    const myFunc = async <T extends SingleObject>(
    name: Name<T>,
    params: FuncParams<T>
    ) => {
    // Do something
    };
    我以为打电话时 myFunc路过 "array" (例如)作为第一个参数,它将识别有问题的对象并正确分配另一个键的参数(在这种情况下应该是 Parameters<(foo: string[] => foo)> )
    显然情况并非如此,因为我可以毫无问题地执行以下操作
    myFunc("number", ["fo"]); // Should only allow a number as the second parameter

    myFunc("string", [34]); // Should only allow a string as the second parameter

    myFunc("array", [34]); // Should only allow an array of strings as the second parameter
    引用
  • TypeScript Playground of the problem
  • 最佳答案

    默认情况下,编译器会将字符串值属性的类型推断为 string而不是 string literal type喜欢 "number" .

    /* const obj: ({
    name: string; // oops
    func: (foo: number) => number;
    } | {
    name: string; // oops
    func: (foo: string) => string;
    } | {
    name: string; // oops
    func: (foo: string[]) => string[];
    })[]
    */
    为了让您的计划可行,您需要说服编译器您关心 name 的实际文字值。 obj 元素的属性.最简单的方法是使用 const assertionobj的初始化程序:
    const obj = [
    {
    name: "number",
    func: (foo: number) => foo,
    },
    {
    name: "string",
    func: (foo: string) => foo,
    },
    {
    name: "array",
    func: (foo: string[]) => foo,
    },
    ] as const; // <-- const assertion
    现在的类型 obj是:
    /* const obj: readonly [{
    readonly name: "number";
    readonly func: (foo: number) => number;
    }, {
    readonly name: "string";
    readonly func: (foo: string) => string;
    }, {
    readonly name: "array";
    readonly func: (foo: string[]) => string[];
    }] */
    哪里 name字段是必需的类型 "number" , "string" , 和 "array" .

    接下来,让编译器推断 generic 类型的最佳方法type 参数是给编译器一个该类型的值,从中推断它。即推断 T来自 T 类型的值很简单,但可以推断 T来自 T["name"] 类型的值不是。
    所以我的建议是这样的:
    /* type NameToParamsMap = {
    number: [foo: number];
    string: [foo: string];
    array: [foo: string[]];
    } */

    const myFunc = async <K extends keyof NameToParamsMap>(
    name: K,
    params: NameToParamsMap[K]
    ) => {
    // Do something
    };
    型号 NameToParamsMap是一个辅助对象类型,其键是 name来自 obj 的字段元素,其属性是来自相关联 func 的参数列表 field 。然后 myFunc可以推断泛型类型参数 K来自 name 的值参数传入。一次 K正确推断,编译器可以检查 params参数以确保它匹配。

    你当然不想写 NameToParamsMap用手;你可以让编译器从 typeof obj 计算它:
    type NameToParamsMap = { 
    [T in typeof obj[number] as T["name"]]: Parameters<T["func"]> }
    我在这里使用 key remapping迭代每个元素 Ttypeof obj[number] ,并使用 T["name"]T["func"]生成对象的键和值。

    让我们确保它有效:
    myFunc("number", [1]); // okay
    myFunc("number", ["oops"]) // error
    // -------------> ~~~~~~
    // Type 'string' is not assignable to type 'number'

    myFunc("string", [34]); // error
    myFunc("array", [34]); // error
    看起来挺好的!
    Playground link to code

    关于arrays - TypeScript - 从对象数组中的键获取函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68804714/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com