我想让TypeScript知道,当getData函数接收'myString'
作为参数时,它返回Promise<string>
,当它接收'myNumber'
时,它返回Promise<number>
。我认为这种方法可以工作,但它给了我如下所示的错误。它没有将endpoint: 'myString'
绑定到returnType: string
。我需要改变什么?
type MyStringType = { endpoint: 'myString'; returnType: string };
type MyNumberType = { endpoint: 'myNumber'; returnType: number };
function getData<T extends MyStringType | MyNumberType>(endpoint: T['endpoint']) {
return axios.get<T['returnType']>(`https://my.url/${endpoint}`);
}
getData('myString').then(response => {
const newString: string = response.data; // Type 'string | number' is not assignable to type 'string'.
});
getData('myNumber').then(response => {
const newNumber: number = response.data; // Type 'string | number' is not assignable to type 'number'.
});
默认情况下,类型MyStringType | MyNumberType
似乎是推断出来的。你可能不想要这个
除了函数重载或使用某种异或类型之外,还可以定义如下类型:
type EndpointReturnTypes = {
'myString': string,
'myNumber': number,
}
然后就可以了
async function getData<T extends keyof EndpointReturnTypes>(endpoint: T) {
return axios.get<EndpointReturnTypes[T]>(endpoint)
}
getData('myString').then(response => {
const newString: string = response.data;
});
getData('myNumber').then(response => {
const newNumber: number = response.data;
});
您可以使用Extract
根据一个判别符来缩小联合的成员:
function getData<T extends MyStringType|MyNumberType, E extends T["endpoint"]>(endpoint: E) {
return axios.get<Extract<T, { endpoint: E }>["returnType"]>(`https://my.url/${endpoint}`);
}
现在,在getData()
的调用位置,将对泛型E
进行具体化,这允许Extract
在函数体内缩小T
的联合,然后使用"returnType"
对剩余的类型进行索引。
游乐场