[英]Typescript optional property type generic
我希望我的 function 能夠獲取任何類型的對象,但如果對象具有屬性“id”,請確保它是字符串或數字。
這是最小的示例:
interface FnItem {
id?: string | number;
};
function fn<T extends FnItem>(item: T, callback: (item: T) => void) {
console.log(item.id);
callback(item)
};
fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.name);
它拋出這個錯誤
Argument of type '{ name: string; }' is not assignable to parameter of type 'FnItem'.
Object literal may only specify known properties, and 'name' does not exist in type 'FnItem'
---
Property 'name' does not exist on type 'FnItem
錯誤告訴你所有你需要的。 您的FnItem
類型上不存在name
。 如果要添加任意鍵,可以通過添加屬性或添加索引簽名來修復它,如下所示:
interface FnItem {
id?: string | number;
[key: string]: any; // or whatever types you accept
};
至於泛型,我現在不知道你需要什么,因為你可以簡單地將 function 定義為
function fn(item: FnItem): void
假設FnItem
可能是任何具有任何屬性的 object 或任何 object 其中id
是number|string
我寧願堅持這個解決方案:
type FnItem = Record<string, unknown>
type IdValidation<Obj extends Record<string, unknown>> =
Obj extends { id: infer Id } ? Id extends string | number ? Obj : Obj & { id: never } : Obj;
function fn<T extends FnItem,>(item: IdValidation<T>, callback: (item: IdValidation<T>) => void) {
console.log(item.id);
callback(item)
};
fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.id);
fn({ name: 'Michel' }, item => item.ya); // error
fn({ name: 'Michel', id: [] }, item => item.id); // id is highlighted as a wrong property
由於第一個參數可能是任何 object,我們應該允許傳遞Record<string,unknown>
從而禁用我們關於id
為number|string
的約束。 這就是我添加IdValidation
實用程序類型的原因。 它只是檢查id
屬性是否滿足條件。 如果滿足 - 保持id
,否則 - 將id
類型替換為never
。 使用never
允許您僅突出顯示不正確的屬性,這使其易於閱讀和理解。
如果你想傳遞一個泛型,那么你需要告訴 function 什么具體類型實現了你的接口:
interface FnItem {
id?: string | number;
};
function fn<T extends FnItem>(item: T, callback: (item: T) => void) {
console.log(item.id);
callback(item);
};
fn<myType>({ name: 'Michel', id: 12 }, (item:myType) => { console.log(item.name); });
fn<myType>({ name: 'Michel' }, (item:myType) => { console.log(item.name); });
class myType implements FnItem
{
name: string = "";
id?: number;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.