[英]Generic type on Typescript class can be omitted
將Typescript與默認的編譯器選項結合使用對允許或禁止的行為非常嚴格-例如null值,類屬性未在構造函數中初始化。 但是當涉及泛型時,可以為一個類定義一個泛型類型,然后在不指定類型的情況下創建一個新類!
class Foo<T> {
bar(item: T): void {
console.log('typeof T: ', typeof item)
}
}
const foo1 = new Foo<string>() // T specified
foo1.bar('hello')
foo1.bar(6) // error TS2345: Argument of type '6' is not assignable to parameter of type 'string'
const foo2 = new Foo() // T missing
foo2.bar('hello')
foo2.bar(6) // works with no complaint
是否有可能將new Foo()
視為錯誤的語句?
如上所述,我正在使用默認的編譯器選項,該選項不允許添加永遠不會初始化的額外屬性a: T
。
您不能使構造函數上的T
遺漏為錯誤(當然可以,但是您需要一些條件類型魔術和一個至少包含一個參數的構造函數)
如果沒有為參數提供參數,可以使用type參數的默認值來使該類不可用。 默認為never
可以解決問題。
class Foo<T = never> {
bar(item: T): void {
console.log('typeof T: ', typeof item)
}
}
const foo1 = new Foo<string>() // T specified
foo1.bar('hello')
foo1.bar(6) // error TS2345: Argument of type '6' is not assignable to parameter of type 'string'
const foo2 = new Foo() // T missing
foo2.bar('hello') // err
foo2.bar(6) // err
您還可以在休息參數中使用構造函數重載和元組來創建一個構造函數,如果您省略type參數(例如,type參數never
),則會產生錯誤。
class Foo<T = never> {
constructor(...a: T extends never ? ['No T was specified']:[])
constructor() {
}
bar(item: T): void {
console.log('typeof T: ', typeof item)
}
}
const foo1 = new Foo<string>() // T specified
foo1.bar('hello')
foo1.bar(6) // error TS2345: Argument of type '6' is not assignable to parameter of type 'string'
const foo2 = new Foo() // T missing, error!
foo2.bar('hello')//err
foo2.bar(6) //err
除了其他答案,我想指出的是,TSLint有專門針對這種情況的規則: no-inferred-empty-object-type
inferred no-inferred-empty-object-type
啟用此規則將使TSLint抱怨TypeScript將{}
推斷為泛型(類似於noImplicitAny
編譯器標志,僅適用於泛型)。
這似乎正是您想要的。
可以為一個類定義一個通用類型,然后在不指定類型的情況下創建一個新類!
也就是說,我們希望編譯器根據傳入的參數類型為我們自動設置T的值:
所以
是否有可能將new Foo()視為錯誤的語句?
不,因為編譯器可能將T
設置為any
或string | number
根據您已經編寫的代碼string | number
。 因此, T
是完全有效的。
看一下您的代碼:
const foo2 = new Foo() // T missing
foo2.bar('hello')
foo2.bar(6) // works with no complaint
為什么會抱怨,編譯器必須推斷一個類型,因此它正在尋找所有用途來推斷一個有效的類型。 畢竟,之前的代碼與以下代碼有什么區別:
const foo3 = new Foo() // T missing
foo3.bar(6)
foo3.bar('hello') // works with no complaint
僅操作順序。 為什么編譯器應該假定僅方法的首次使用才能確定T
的類型? 如果是以下情況怎么辦:
const foo3 = new Foo() // T missing
if (someValueOrBooleanReturningFunction) {
foo3.bar(6)
}
foo3.bar('hello') // works with no complaint
那呢 也許可以或不能確定if
的值,但是由於未指定a類型,因此無論哪種方式,編譯器都必須確定T
是什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.