与语言无关 - 函数和构造函数参数中允许的类型

Language Agnostic - Allowable types in function and constructor parameters

提问人:Matthew Layton 提问时间:11/18/2019 更新时间:11/19/2019 访问量:80

问:

大多数(如果不是全部)静态类型语言都允许您为函数或构造函数参数指定单个类型;例如

function foo(x: string) { ... }

foo("hello")  // works
foo(123)      // error

TypeScript 是 JavaScript 的静态类型超集,但由于 JavaScript 是一种动态类型语言,TypeScript 允许你更加灵活;例如,可以指定多个允许的类型。

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)中做到这一点,但据我所知,这些语言中没有等效的结构来支持这种约束。如何在其他语言中实现这一目标?

注意:我很乐意接受任何语言的答案,而不仅仅是列出的答案。这更多的是关于更高层次的思考和探索可以跨语言应用的其他途径。

JavaScript C# TypeScript Kotlin 与语言无关

评论

1赞 canton7 11/18/2019
对于 C#,可以在第一种情况下使用方法重载

答:

0赞 vasil oreshenski 11/18/2019 #1

F# 中,有 Sum/Union 类型。看起来很像 TypeScript 中的内容,但在 F# 中,它们是使用用于匹配的标签定义的。
这允许您具有具有多个相同类型的案例的总和类型。例如:

type ShoeSize = 
    | EU of double
    | UK of double
    | US of double
1赞 AProgrammer 11/18/2019 #2

C++ 20 有一个概念,它能够以您想要的方式约束模板参数,等等。这在语言中引入了一些使用各种技术可以近似的东西,在这里描述它们似乎超出了范围。

1赞 Alexey Romanov 11/19/2019 #3

TypeScript 可以让你更灵活一些;例如,可以指定多个允许的类型。

不,你不能; 是单一类型,称为联合类型。您可以传递 a 或 a,因为它们都是 的子类型。但你也可以通过任何.number | stringnumberstringnumber | stringnumber | string

类似地,在第二个示例中,不被限制为 either 或 ;它可以是 或 的任何子类型。甚至Tnumberstringnumber | stringnumberstring

var x = new Foo<123 | "">(123)

其中又是一个完全普通的 TypeScript 类型。123 | ""

Scala 3 将具有联合类型;有人讨论过 Kotlin 的联合类型,但你可以看到团队并不感兴趣。对于 C#,类似。