使用 Typescript 时有没有办法推断映射类型的键?

问题描述 投票:0回答:1

我有一个代表我的业务运营的数据结构:

const operations = {
    list: {
        request: "a",
        response: "b",
    },
    get: {
        request: "a",
        response: "b",
    },
} as const;

我想创建一个基于上面的

operations
接受回调的函数:

type Ops = typeof operations;

type Callbacks = {
    [Property in keyof Ops]: (
        param: Ops[Property]["request"]
    ) => Ops[Property]["response"];
};

现在,如果我想定义我的回调,如果我错过其中任何一个,编译器会抱怨:

const callbacks: Callbacks = {

};
// ^^^--- Type '{}' is missing the following properties from type 'Callbacks': list, get

现在我的问题是我想创建另一种类型,以便我可以键入检查

operations
对象的结构:

interface OperationDescriptor<A, B> {
    request: A;
    response: B;
}

type Operations = {
    [key: string]: OperationDescriptor<any, any>;
};

const operations: Operations = {
    list: {
        request: string,
        response: string,
    },
    get: {
        request: string,
        response: string,
    },
} as const;

但是当我这样做时,编译器将不再抱怨,因为

Operations
不知道我在
operations
中的键。有没有办法鱼和熊掌兼得,例如:

  • 定义一个类型,我可以用它来检查
    operations
  • 的结构
  • 有一个
    Callbacks
    类型,它将根据
    operations
    的结构对我的回调函数进行类型检查?
typescript type-inference mapped-types
1个回答
0
投票

您可以使用

satisfies
运算符来检查值是否可分配给某个类型,而无需将其扩大到该类型。它正是针对类型注释会忘记您关心的信息的情况而设计的:

const operations = {
    list: {
        request: "a",
        response: "b",
    },
    get: {
        request: "a",
        response: "b",
    },
} as const satisfies Operations;

如果以上编译通过,那么你就知道你没问题。否则你会得到你期望的错误:

const badOperations = {
    list: {
        request: "a",
        response: "b",
    },
    get: { // error!
    //~ <-- Property 'response' is missing
        request: "a",
    },
} as const satisfies Operations;

类型

typeof operations
仍然与您需要的一样详细:

type Ops = typeof operations;
/* type Ops = {
    readonly list: {
        readonly request: "a";
        readonly response: "b";
    };
    readonly get: {
        readonly request: "a";
        readonly response: "b";
    };
} */

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.