猜猜你的类型是谁

Ever had to implement some logic that checked properties of an object so you could figure out exactly what it was at runtime? I’m sure at some point everyone has in some form, whether it be casting, property assertions or even reflection (shudder). This concept seems so fundamental to almost every paradigm of programming and there are so many ways to go about it; some are safer than others, but given the language you might ask “how do I best implement this logic?”. And of course, there is no best. Everything in our domain is fairly subjective, however there are some good options depending on the language that I’d like to shine some light on.

是否曾经必须执行某种逻辑来检查对象的属性,以便您可以精确地确定对象在运行时的状态? 我确定每个人在某种程度上都具有某种形式,无论是强制转换,属性断言还是反射(颤抖)。 这个概念对于几乎所有的编程范例来说似乎都是至关重要的,并且有很多方法可以实现。 有些语言比其他语言更安全,但是考虑到语言,您可能会问“我如何最好地实现此逻辑?”。 当然,没有最好的。 我们领域中的所有内容都是相当主观的,但是根据我想启发自己的语言,有一些不错的选择。

我最近在Scala所做的工作 (My recent endeavours in Scala)

In the last month or so I’ve been tasked with learning Scala to work on a codebase associated with my current area of work (optimisation if you’re wondering) and aside from the excitement of learning a new language, I’ve found the whole experience to be quite eye-opening. There are so many unique features of Scala that I’ve never had the pleasure of using in other languages; things like implicits and higher order types, but my favourite yet is actually pattern matching with case classes. In many cases (pun intended), pattern matching and case classes are what you use to play “Guess Who?” in Scala and the sheer amount of syntactic sugar that comes with them makes them feel so effortless to use. The pattern involves a thin layer of subtyping to associate types using something called a sealed trait but it hardly feels like it has the bulk of class inheritance. Throughout this article I’ll use the common example of “shapes” to demonstrate code; this is how this might play out in Scala.

在过去的一个月左右的时间里,我受命学习Scala来开发与我当前工作领域相关的代码库(如果您想知道,请进行优化),除了学习一种新语言的兴奋之余,我还发现整个体验相当开阔。 Scala有很多独特的功能,我从未有过用其他语言来使用的乐趣。 诸如隐式高阶类型之类的东西,但我最喜欢的实际上是与案例类进行模式匹配。 在许多情况下(双关语),模式匹配和案例类是您用来播放“猜猜谁?”的东西。 在Scala中,它们附带的大量语法糖使它们使用起来非常轻松。 该模式涉及一小层子类型化,以使用一种称为“密封特征”的类型来关联类型,但几乎不会感觉到它具有大量的类继承。 在整篇文章中,我将使用“形状”的常见示例来演示代码。 这就是在Scala中可能会发生的情况。

The use of sealed for the trait in this instance enables exhaustive checking because it restricts other files from extending it, so there’s no point in which the compiler doesn’t know all options it needs to exhaust. What might not be painfully obvious is that the match operator is much the same as executing a function on shape which means you can execute this whenever, wherever, without having to worry about conditional branching; the entire thing is an expression. Sugar like that really makes features like this useful and to be honest, we’ve really only scratched the surface here. After spending a good amount of time with this concept it got me wondering how this might play out in other languages, namely TypeScript, given that I do a lot of work there.

在这种情况下,对特征使用密封的功能可以进行详尽的检查,因为它限制了其他文件的扩展,因此,编译器根本不知道需要用尽所有选项。 可能不会很痛苦的是,匹配运算符与在形状上执行函数几乎相同,这意味着您可以随时随地执行此操作,而不必担心条件分支。 整个事情都是一种表达。 像这样的Sugar确实使诸如此类的功能有用并且说实话,我们实际上只是在这里打了水漂。 在花了很多时间处理这个概念之后,我想知道在其他语言(即TypeScript)中如何发挥作用,因为我在那里做了很多工作。

回到运行时失明 (Back to being blind at runtime)

Admittedly, working on JS/TypeScript can be a pretty significant context shift coming from any language with runtime types, primarily because it shifts your thinking into 2 parallel streams of “what does this do at runtime” and “what does this assert for the compiler”, and they can be 2 very different things sometimes. In a language like Scala you have tagged types to match on at runtime but TypeScript doesn’t have any of the sort even if your code has interfaces for them. Classes are potentially an option to create tagged types but why bother using a structural language if you’re going to throw away 80% of the language features? (an exaggeration of course!) Instead you have to rely on explicit properties to tag your objects, such as a type property for example. If we do end up adding a property for the type, is there a way to implicitly assert these types with the TypeScript compiler? Yes, there is indeed!

诚然,使用任何具有运行时类型的语言,使用JS / TypeScript可能是一个相当大的上下文转换,主要是因为它将您的思维转换为两个并行流,“这在运行时做什么”和“这对编译器有什么断言” ”,有时它们可​​能是2个非常不同的事物。 在像Scala这样的语言中,您已经标记了要在运行时匹配的类型,但是TypeScript没有任何种类,即使您的代码具有针对它们的接口。 类是创建标记类型的潜在选择,但是如果您要丢弃80%的语言功能,为什么还要使用结构化语言呢? (当然是夸张了!)相反,您必须依靠显式属性来标记对象,例如类型属性。 如果最终为类型添加了属性,是否可以使用TypeScript编译器隐式声明这些类型? 是的,确实有!

简介:判别联盟 (Introducing: Discriminant Unions)

Discriminant unions are how the TypeScript compiler solves this problem, and boy is it smart about it. In basic terms, a discriminant union describes an association between multiple types based on a “discriminant” (a property shared between all types that uniquely identifies each participating type). Let’s look at how the shapes example might work in TypeScript with a discriminant union.

判别联合是TypeScript编译器解决此问题的方式,对此,它真是明智之举。 从根本上讲,判别联合描述基于“判别式”(在所有类型之间共享的属性,可以唯一标识每个参与类型)的多个类型之间的关联。 让我们看一下形状示例如何在判别式联合中在TypeScript中工作。

The compiler with a discriminant union in its hands will be able to very smartly infer the type it’s working with and give you access to all its properties. Most other languages will force you to assign an assertion of the type to a new variable for this however the magic here is that within that branch, a seemingly ambiguous variable is now concretely defined. One of the drawbacks to this approach is that it’s necessary to explicitly tag your objects, however, I bet you already do this when you encode your subtypes into JSON anyway; TypeScript is just letting you embrace that model. There’s one more feature of this I ought to mention that might not be obvious.

手中拥有判别式联合的编译器将能够非常聪明地推断出正在使用的类型,并为您提供访问其所有属性的权限。 大多数其他语言会强迫您为此为此新类型的变量分配类型的断言,然而,这里的妙处在于,在该分支中,现在已经具体定义了一个看似模棱两可的变量。 这种方法的缺点之一是必须显式标记对象,但是,我敢打赌,无论如何,当您将子类型编码为JSON时,您已经做到了; TypeScript只是让您拥抱该模型。 我应该提到的另一个功能可能并不明显。

使用多个判别式 (Using multiple discriminants)

Given that TypeScript is primarily a structural language, there is nothing at all stopping the use of multiple discriminants for an objects properties. This concept actually isn’t really possible in non-structural languages because of the inheritance chain and in many cases it would be considered messy as it encourages squashing of loosely associated data. In TypeScript, it’s one of those features that emphasises the efficiency of structural typing and makes that “squashing” fairly acceptable. Here’s an example of how it might work with 2 different subtypes in a single object.

鉴于TypeScript主要是一种结构语言,因此完全没有停止对对象属性使用多个判别式的情况。 由于存在继承链,因此在非结构化语言中实际上不可能实现这个概念,并且在许多情况下,由于它鼓励挤压松散关联的数据,因此它被认为是混乱的。 在TypeScript中,它是强调结构化键入效率并使“压缩”相当可接受的那些功能之一。 这是一个示例如何在单个对象中使用2个不同子类型的示例。

I’ve omitted some of the implementation details here and there but the concept still stands. With mindful architecture around discriminants you can very efficiently use objects in a safe manner for multiple subtypes. I’m not saying this is always the best way to model your data by any stretch but there will undoubtedly be scenarios where you will have to deal with objects like this and this is just one tool to work with them safely.

我在这里和那里已经省略了一些实现细节,但是这个概念仍然存在。 借助围绕判别器的细心架构,您可以安全有效地将对象用于多个子类型。 我并不是说这始终是通过任何方式对数据建模的最佳方法,但是毫无疑问,在某些情况下,您将不得不处理此类对象,而这只是安全地与它们一起使用的一种工具。

Hopefully with these tools you can win more at Guess Who in your coding endeavours!

希望借助这些工具,您可以在Guess Who的编码工作中赢得更多!

翻译自: https://medium.com/skedulo-engineering/playing-guess-who-with-your-types-87deb57f0268

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值