我有一個名為的物件endpoints,它有多種方法:
const endpoints = {
async getProfilePhoto(photoFile: File) {
return await updateProfilePhotoTask.perform(photoFile);
},
};
我正在使用這個函式來訪問這些方法。它接受一個字串引數,用于構建模板文字,然后使用方括號表示法訪問該方法:
export const useApiTask = (
endpointName: string,
) => {
//const apiActionName = 'getProfilePhoto'; // When defined as a string it works
const apiActionName = `get${endpointName}`; // But when using template literals I get a TypeScript error
const endpointHandler = endpoints[apiActionName]; // The TypeScript error shows here
}
但是使用模板文字會在以下位置創建此 TypeScript 錯誤endpointHandler = endpoints[apiActionName]:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ getProfilePhoto(photoFile: File): Promise<string | undefined>; }'.
No index signature with a parameter of type 'string' was found on type '{ getProfilePhoto(photoFile: File): Promise<string | undefined>; }'. ts(7053)
知道這里發生了什么嗎?
uj5u.com熱心網友回復:
這段代碼有兩個問題。FirstendpointName不能是 any string,它必須是endpoints(減去get前綴)的有效鍵。所以我們需要有一個更窄的型別。第二個問題是,即使endpointName是有效鍵的聯合,文字操作仍然會產生string,除非我們告訴 TypeScript 我們想要一個更窄的型別as const:
const endpoints = {
async getProfilePhoto(photoFile: File) {
return await Promise.resolve();
},
async getProfile(photoFile: File) {
return await Promise.resolve();
},
};
export const useApiTask = (
endpointName: 'ProfilePhoto' | 'Profile', // Union of posibilities
) => {
const apiActionName = `get${endpointName}` as const; // Make sure the type info is preserverd
const endpointHandler = endpoints[apiActionName];
}
游樂場鏈接
您還可以使用條件型別來提取名稱的并集以避免重復名稱:
type EndpointNames = keyof typeof endpoints extends `get${infer Name}` ? Name : never
游樂場鏈接
uj5u.com熱心網友回復:
發生此錯誤是因為typeof endpointsare not的鍵string,而是文字字串"getProfilePhoto"(在您的示例中)。
為了解決這個問題,您可以使用一個聰明的技巧,模板文字推斷endpoints,以派生與“以”開頭的字串的模式匹配的鍵名稱的型別get,然后在endpointName引數上使用該型別,如下所示:
TS游樂場
declare const updateProfilePhotoTask: { perform (file: File): Promise<unknown>; };
const endpoints = {
async getProfilePhoto(photoFile: File) {
return await updateProfilePhotoTask.perform(photoFile);
},
getANumber() {
return Math.random();
},
getThisProp: 'hello',
};
// This becomes "ProfilePhoto" | "ANumber"
type EndpointFunctionNamesPrefixedByGet = typeof endpoints extends infer T ? keyof { [
K in keyof T as K extends `get${infer Name}` ?
T[K] extends (...params: any) => any ? Name : never
: never
]: unknown; } : never;
export const useApiTask = (endpointName: EndpointFunctionNamesPrefixedByGet) => {
const endpointHandler = endpoints[`get${endpointName}`];
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/433056.html
標籤:打字稿
下一篇:來自混合物件陣列欄位的鍵聯合
