[英]Typescript: Type is not assignable to conditional type
我有一個 function 查詢我的數據庫,並且根據我們是在提取“已保存”數據還是“未保存”數據將更改 output。 我想把它濃縮成一個 function ,所以我正在使用條件類型讓 Typescript 知道 ZC1C425268E68385D1AB5074C17A94F1 的響應將基於類型改變。
如果保存,function 應該返回一個 ProductType 數組(我制作的一個自定義類型),否則它應該返回一個字符串數組。
type ProductType = {
title: string;
price: number;
};
type QueryResponse<T> = T extends 'unsaved'
? ProductType[]
: T extends 'saved'
? string[]
: never;
export async function queryDb<T extends 'saved' | 'unsaved'>(
type: T,
): Promise<QueryResponse<T>> {
// Get correct DB URL based on type input.
let dbUrl: string;
if (type === 'saved') {
dbUrl = 'DATABASEURL/saved';
} else {
dbUrl = 'DATABASEURL/unsaved';
}
// Fetch data from the database.
const r = await fetch(dbUrl);
const dbResult = JSON.parse(await r.json());
// Structure the data correctly to be in line with the types, then return.
if (type === 'saved') {
let response: string[] = dbResult.data;
return response;
} else {
let response: ProductExample[] = dbResult.data;
return response;
}
}
我在兩個返回語句下都收到錯誤消息: Type 'ProductType[]' is not assignable to type 'QueryResponse<T>'.
,並且Type 'string[]' is not assignable to type 'QueryResponse<T>'.
分別。
不幸的是,雖然您的條件類型QueryResponse<T>
正確地從T
推斷返回類型,但 TypeScript 無法利用您的type === 'saved'
條件作為類型保護:
// Structure the data correctly to be in line with the types, then return.
if (type === 'saved') {
let response: string[] = dbResult.data;
type // type is NOT narrowed down to "saved" type
//^? (parameter) type: T extends "saved" | "unsaved"
return response; // Error: Type 'string[]' is not assignable to type 'QueryResponse<T>'.
} else {
let response: ProductType[] = dbResult.data;
type
//^? (parameter) type: T extends "saved" | "unsaved"
return response; // Error: Type 'ProductType[]' is not assignable to type 'QueryResponse<T>'.
}
正如 smac89 在問題評論中所建議的那樣,您可以跳過嘗試鍵入返回的塊,因為它已經由您的顯式返回類型指定:
export async function queryDb0<T extends 'saved' | 'unsaved'>(
type: T,
): Promise<QueryResponse<T>> {
// Etc
// We may even skip typing the return here, it is already done in the explicit return type
return dbResult.data;
}
在您的情況下,您甚至可以通過簡單地使用function 重載來避免條件類型:
export async function queryDb2(type: 'saved'): Promise<string[]>
export async function queryDb2(type: 'unsaved'): Promise<ProductType[]>
export async function queryDb2(type: 'saved' | 'unsaved'): Promise<string[] | ProductType[]> {
// Etc.
// We may even skip typing the return here, it is already done in the overloads
return dbResult.data;
}
讓我們檢查一下它的用法:
const s = queryDb2('saved');
// ^? const s: Promise<string[]>
const u = queryDb2('unsaved');
// ^? const u: Promise<ProductType[]>
const o2 = queryDb2('other'); // Error: No overload matches this call. Overload 1 of 2, [...] Argument of type '"other"' is not assignable to parameter of type '"saved"'. Overload 2 of 2, [...] Argument of type '"other"' is not assignable to parameter of type '"unsaved"'.
看起來不錯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.