Generický typ na triede v Typescripte môže byť vynechaný
Používanie Typescriptu s predvolenými možnosťami kompilátora je dosť prísne na to, čo je povolené alebo nie - napríklad nulové hodnoty, atribúty triedy, ktoré nie sú inicializované v konštruktore. Ale pokiaľ ide o generiká, je možné definovať generický typ pre triedu a potom vytvoriť novú triedu bez špecifikovania typu!
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
Je možné považovať new Foo() za nesprávny príkaz?
Ako je uvedené vyššie, používam predvolené možnosti kompilátora, ktoré by neumožnili pridať ďalší atribút a: T, ktorý by nikdy nebol inicializovaný.
Odpoveď č. 1
Nemôžete urobiť vynechanie T v konštruktore za chybu (no pravdepodobne môžete, ale potrebovali by ste nejakú podmienenú typovú mágiu a konštruktor s aspoň jedným argumentom)
Môžete spraviť triedu nepoužiteľnou, ak nie je zadaný žiadny argument, použitím predvoleného typu parametra. Predvolená hodnota never to urobí.
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
Môžete tiež použiť preťaženie konštruktora a n-tice v zvyšných parametroch na vytvorenie konštruktora, ktorý dá chybu, ak vynecháte typový parameter (t. j. typový parameter je 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
Odpoveď č. 2
Okrem ostatných odpovedí by som rád poukázal na to, že TSLint má pravidlo špeciálne proti tomuto prípadu: no-inferred-empty-object-type
Povolením tohto pravidla spôsobíte, že TSLint bude upozorňovať, keď TypeScript odvodí {} ako generický typ (podobne ako prepínač kompilátora noImplicitAny, ale pre generiká).
Zdá sa, že toto je presne to, čo chceš.
