假设我有一个看起来像这样的界面:
type RequestProps = "a" | "b" | "c"
interface Request {
props: RequestProps[];
}
和一些接受请求并返回响应对象的代码:
declare function sendRequest(r: Request);
我想缩小r.props
的范围,以便我返回一个带有与所请求道具对应的键的响应。也就是说,如果请求是由这样的用户发出的:
const request = {
props: ["a", "c"]
}
let response = sendRequest(request);
该response
将自动完成response.a
和response.c
作为字符串值。类似于
type Response<T extends RequestProps[]> = { [key in T[number]]: string; }
我不希望请求创建者必须指出字符串文字("a" as "a"
)或元组(["a", "c"] as ["a", "c"]
),我希望sendRequest
能够推断出它或根据上下文进行提示或以某种方式进行保护,无论类型多么冗长,该类型都可以缩小为数组包含的实际文字值(如有必要,我将缩小每个排列的范围)。这可能吗?字符串枚举似乎与字符串文字有相同的问题。谢谢!
答案 0 :(得分:1)
假设您定义:
declare function sendRequest<T extends RequestProps[]>(r: {props: T}): Response<T>;
正如我想的那样。然后执行以下操作:
let response = sendRequest({
props: ["a", "c"]
});
如果您不想立即发送请求,则必须以某种方式阻止props
元素扩展。一个众所周知的技巧是通过应用适当上下文类型的函数来运行请求:
declare function asRequest<T extends RequestProps[]>(r: {props: T}): {props: T};
let request = asRequest({
props: ["a", "c"]
});
如果您确实真的希望能够将请求编写为对象文字并将其保存在变量中而无需使用辅助函数,则可以使用一堆单成员枚举,尽管这对我来说似乎不合理:< / p>
enum AA { A = "a" }
enum BB { B = "b" }
enum CC { C = "c" }
const A = AA.A, B = BB.B, C = CC.C;
type RequestProps2 = AA | BB | CC;
interface Request2 {
props: RequestProps2[];
}
type Response2<T extends RequestProps2[]> = { [key in T[number]]: string; }
declare function sendRequest2<T extends RequestProps2[]>(r: {props: T}): Response2<T>;
let request2 = {
props: [A, C]
};
let response2 = sendRequest2(request2);