代码之家  ›  专栏  ›  技术社区  ›  defraggled

如何以类型安全的方式指定键的常量列表,并从该列表派生Picked接口?

  •  1
  • defraggled  · 技术社区  · 2 年前

    我有一个预定义的复杂接口,由于它来自第三方库,我无法操作它。

    interface Fruit {
        name?: string;
        id?: number;
        weight?: number;
    }
    

    我需要

    • 定义该接口的键子集的列表,然后
    • 定义一个只有^个成员的新接口(或类型),该接口的类型与原始接口相同。

    澄清一下:我需要在代码中实际使用列表(否则我只会把它们写进 Pick<Fruit, ...> 并就此结束)。

    以下是一种方法:

    const fieldsToIsolate = ["id", "weight"] as const;
    
    type IsolatedFruit = Pick<Fruit, typeof fieldsToIsolate[number]>;
    // type IsolatedFruit = {
    //     id?: number | undefined;
    //     weight?: number | undefined;
    // }
    
    

    这种方法的问题在于 fieldsToIsolate 不是类型安全的。

    这里有一种不同的方法可以解决这个问题,但也有自己的问题:

    const fieldsToIsolate: Array<keyof Fruit> = ["id", "weight"];
    
    type IsolatedFruit = Pick<Fruit, typeof fieldsToIsolate[number]>;
    // type IsolatedFruit = {
    //     name?: string | undefined;
    //     id?: number | undefined;
    //     weight?: number | undefined;
    // }
    

    现在列表已经安全地键入,但是 IsolatedFruit 不准确。

    如果我们尝试重新连接,Typescript现在会抱怨 as const 因为

    The type 'readonly ["id", "weight"]' is 'readonly' and cannot be assigned to the mutable type '(keyof Fruit)[]'
    

    有办法做到这一点吗?

    1 回复  |  直到 2 年前
        1
  •  2
  •   Nicholas Tower    2 年前

    我会用 satisfies 关键字,在中引入 typescript 4.9 :

    const fieldsToIsolate = ["id", "weight"] satisfies Array<keyof Fruit>;
    
    type IsolatedFruit = Pick<Fruit, typeof fieldsToIsolate[number]>;
    

    这导致typescript执行两件事:

    1. fieldsToIsolate 将获得比 string[] ,基于您使用的确切值。在本例中,类型为 ('id' | 'weight')[] 。这反过来又允许 IsolatedFruit 是正确的类型。
    2. Typescript将检查以验证“id”和“weight”是否确实是 Fruit 如果不是,则会给出错误。所以打字错误和不存在的按键会引起你的注意。

    Playground link

    推荐文章