大多数情况下,如果不是所有静态类型的语言,您都可以为函数或构造函数参数指定单一类型;例如
function foo(x: string) { ... }
foo("hello") // works
foo(123) // error
TypeScript是JavaScript的静态类型超集,但是由于JavaScript是动态类型的语言,因此TypeScript可以使您更加灵活;例如,您可以指定多个allowable类型。
function foo(x: string | number) { ... }
foo("hello") // works
foo(123) // works
foo(true) // error
此外,在TypeScript中,这允许您将通用类型参数仅限制为特定类型;例如:
class Foo<T extends number | string> {
constructor(x: T) { ... }
}
new Foo("hello") // works
new Foo(123) // works
new Foo(true) // fails
问题
我喜欢TypeScript仅将通用类型参数限制为特定类型的功能,但是我也希望能够使用其他语言(例如C#和Kotlin)做到这一点,但据我所知,在该语言中没有等效的构造这些语言支持这种约束。用其他语言如何做到这一点?
注意:我很高兴接受any语言的答案,而不仅仅是列出的答案。这更多地是关于更高层次的思考和探索可能适用于多种语言的其他途径。
C ++ 20具有concept的概念,它能够以您想要的方式约束模板参数,以及更多。这在语言中引入了可以使用多种技术近似的东西,此处描述它们似乎超出了范围。
TypeScript使您更加灵活;例如,您可以指定多个允许的类型。
不,您不能; number | string
是单个类型,称为联合类型。您可以传递number
或string
,因为它们都是number | string
的子类型。但是您也可以传递任何number | string
。
类似地,在第二个示例中,T
不受约束为number
或string
;它可以是number | string
或number
或string
的任何子类型。甚至
var x = new Foo<123 | "">(123)
123 | ""
也是完全普通的TypeScript类型。
Scala 3将具有联合类型;那里是a discussion of union types for Kotlin,但您可以看到团队对此并不感兴趣。对于C#,similarly。
在F#中,有Sum / Union类型。看起来很像TypeScript中的内容,但是在F#中,它们是用用于匹配的标签定义的。这使您可以将总和类型与多个相同类型的案例一起使用。例如:
type ShoeSize =
| EU of double
| UK of double
| US of double