使用Typescript和默认的编译器选项对允许或禁止的使用非常严格-例如空值,类属性不在构造函数中初始化。但是当涉及泛型时,可以为一个类定义一个泛型类型,然后在不指定类型的情况下创建一个新类!
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
。
答案 0 :(得分:4)
您不能在构造函数上遗漏image: {{ printf "%s/%s:%s" .Values.image.repository (.Values.image.image | default "myimage") .Values.image.tag | quote}}
是一个错误(当然可以,但是您需要一些条件类型魔术和一个至少带有一个参数的构造函数)
如果不使用类型参数的默认值提供参数,则可以使该类不可用。默认值为T
将解决问题。
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
)时出现错误
never
答案 1 :(得分:2)
除了其他答案,我想指出的是,TSLint有专门针对这种情况的规则:no-inferred-empty-object-type
启用此规则将使TSLint抱怨TypeScript何时将{}
推断为泛型(类似于noImplicitAny
编译器标志,仅适用于泛型)。
这似乎正是您想要的。
答案 2 :(得分:1)
可以为一个类定义一个通用类型,然后在不指定类型的情况下创建一个新类!
Of course, it's called type argument inference:
也就是说,我们希望编译器根据传入的参数类型为我们自动设置T的值:
如此
是否可以将新的Foo()视为错误的陈述?
否,因为编译器可能根据已经编写的代码将T
设置为any
或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
是什么。