簡體   English   中英

typescript中覆蓋泛型的約束類型

[英]Overriding the constraint type of the generic type in typescript

我創建了一個名為DataType的通用類型助手,它接受一個參數 T,該參數 T 被限制為keyof MyObject類型。 如果鍵存在於MyObject中, DataType將返回MyObject的屬性類型; 否則,它將返回 T 本身。

interface MyObject {
  foo: string;
  bar: boolean;
}
export type DataType<T extends keyof MyObject> = T extends keyof MyObject
  ?  MyObject[T] 
  : T;

現在,如果我傳遞MyObject的任何鍵,它將返回相應的類型:

type StrType=DataType<'foo'>; // data type is string

但是,如果我將字符串以外的數據類型傳遞給此幫助程序,我將得到Type 'type' does not satisfy the constraint '"foo"'

type numType=DataType<number>;

如何不約束類型但仍然有MyObject鍵的 IntelliSense 提示?

你真的不想約束T 它可以是任何東西,甚至unknown類型 這可以通過將其保留為type DataType<T> =...而不限制T來實現。

interface MyObject {
  foo: string;
  bar: boolean;
}

type DataType<T> =
  T extends keyof MyObject ? MyObject[T] : T;

type StrType = DataType<'foo'>; // string
type NumType = DataType<number>; // number

但如果你這樣做,你將失去提示keyof MyObject的字符串文字類型成員的 IntelliSense 提示:

// type BooType = DataType<'⃒'> 
// ----------------------> ^^ <---
// IntelliSense prompts here with NOTHING 😢

因此,您正在尋找的是一種等效於unknown的類型,但具有keyof MyObject的一些“內存”,IntelliSense 可以使用它。

您可能會想到使用聯合類型keyof MyObject | unknown keyof MyObject | unknown ,但不幸的是, unknown熱切地吸收聯合中的其他類型。 所以keyof MyObject | unknown 在 IntelliSense 有機會做任何事情之前, keyof MyObject | unknown變為unknown

幸運的是,還有另一種類型在本質上類似於unknown :union {} | null | undefined {} | null | undefined {} | null | undefined 所謂的空 object 類型{}實際上接受任何非空類型,甚至像string這樣的基元(這是因為string有明顯的成員,如"length""toUpperCase" ,所以string{length: number, toUpperCase(): string} ,它是{}的子類型)。 唯一不可分配給{}的值是nullundefined 所以聯合{} | null | undefined {} | null | undefined {} | null | undefined本質上與unknown相同。 有一些細微差別,但您甚至可以將unknown分配給{} | null | undefined {} | null | undefined {} | null | undefined

一個“小”區別是{} | null | undefined {} | null | undefined {} | null | undefined不會急切地吸收聯合中的字符串文字。 所以keyof MyObject | {} | null | undefined的聯合鍵keyof MyObject | {} | null | undefined keyof MyObject | {} | null | undefined保持不變,因此keyof MyObject仍然可用於 IntelliSense 采取行動:

type DataType<T extends (keyof MyObject | {} | null | undefined)> =
  T extends keyof MyObject ? MyObject[T] : T;

type StrType = DataType<'foo'>; // string
type NumType = DataType<number>; // number       

// type BooType = DataType<'⃒'> 
// ----------------------> ^^ <---
// IntelliSense prompts here with
//    🔧 bar
//    🔧 foo    
type BooType = DataType<'bar'> // boolean

游樂場代碼鏈接

如果T可以是任何類型,只需刪除約束:

export type DataType<T> = T extends keyof MyObject
  ?  MyObject[T] 
  : T;

游樂場鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM