如何在TypeScript中绑定两个类型?



我想让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"对剩余的类型进行索引。

游乐场

最新更新