我有一个代表我的业务运营的数据结构:
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
的结构对我的回调函数进行类型检查?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";
};
} */