无比打字与拼英打字_打字稿中的名义打字

无比打字与拼英打字

标称和结构分型 (Nominal & structural typing)

Type systems are typically categorized as either structural or nominal. Languages like Java and Scala have primarily nominal type systems, whereas a language like Typescript has a structural type system. Let’s take a brief look at both systems.

类型系统通常分为结构或名义上。 诸如Java和Scala之类的语言主要具有名义类型系统,而诸如Typescript之类的语言则具有结构类型系统。 让我们简要介绍一下这两个系统。

标称打字 (Nominal Typing)

In a nominal typing system, type compatibility is checked using the name of the types. If they do not have the same name, then they are not compatible; end of story. If Typescript had a nominal typing system the type check for the last line would fail:

在名义类型系统中,使用类型名称检查类型兼容性。 如果它们的名称不同,则它们不兼容;否则,它们不兼容。 故事结局。 如果 Typescript具有标称键入系统,则最后一行的类型检查将失败:

Image for post

结构类型 (Structural typing)

Typescript uses structural typing to decide whether two types are compatible with one another or not. What do we mean by structural typing? Well, let’s consider the following code snippet:

Typescript使用结构化类型来确定两种类型是否彼此兼容。 我们所说的结构化打字是什么意思? 好吧,让我们考虑以下代码片段:

Image for post

To determine whether the type of the constant color(RGBA) is compatible with the type of serializeColor’s parameter x(RGB) the type system must verify that each member of RGB has a corresponding compatible member in RGBA. In this case, RGB has a single member color for which RGBA has a corresponding member with the same type — [number, number, number] — and so it passes the type check. Notice how the type system ignores the additional members that exist on RGBA (alpha).

为了确定常量color ( RGBA )的类型是否与serializeColor的参数x ( RGB )的类型兼容,类型系统必须验证RGB每个成员在RGBA都有相应的兼容成员。 在这种情况下, RGB具有单一成员color ,而RGBA具有对应的成员具有相同的类型- [number, number, number] ,因此它通过类型检查。 请注意,类型系统如何忽略RGBA (alpha)上存在的其他成员。

TS中的名义类型 (Nominal types in TS)

Even though Typescript has a primarily structural type system, we can still implement some form of nominal types if we follow a standard pattern when defining types so that the type system will always treat them as distinct types. This structure will act as a unique identifier and descriptor of that type. Such an implementation might look something like this:

即使Typescript具有主要的结构类型系统,但如果在定义类型时遵循标准模式,我们仍然可以实现某种形式的名义类型,以便类型系统始终将它们视为不同的类型。 该结构将充当该类型的唯一标识符和描述符。 这样的实现可能看起来像这样:

Image for post

the type member represents the name of the type, while the data member describes its type of data. Now if I’d create a value of type RGB I’d have to do it in the following way:

type成员表示type的名称,而data成员描述其数据的类型。 现在,如果要创建RGB类型的值,则必须采用以下方式:

Image for post

Of course, writing this structure for every single nominal-typed value would be tedious work. This is where value constructors come to the rescue. A value constructor is a function that facilitates constructing values of a specific type without all the boilerplate and noise. Let’s create one for RGB:

当然,为每个单个标称值的值编写此结构都是繁琐的工作。 这就是价值构造函数来解救的地方。 值构造函数是一种有助于构造特定类型的值而没有所有样板和噪声的函数。 让我们为RGB创建一个:

Image for post

And now we can create a value of type RGB with less verbose code:

现在,我们可以使用较少的冗长代码创建RGB类型的值:

Image for post

Now that we’ve introduced value constructors, let’s incorporate one in our nominal type interface:

现在,我们介​​绍了值构造函数,让我们在名义类型接口中加入一个:

Image for post

At first sight, you might feel a bit uncertain of what value the valueConstructor member brings to the type system, but it does actually serve two purposes:

乍一看,您可能会不确定valueConstructor成员为类型系统带来什么价值,但实际上它有两个作用:

  • Together with type and data, they lay out a complete description of a type: the name of the type, the shape of its data, and how to construct it.

    他们与typedata一起,对type进行了完整的描述:类型的名称,数据的形状以及构造方法。

  • You can build type guards based on value-constructors as we shall see when we discuss subtypes.

    正如我们在讨论子类型时将看到的那样,您可以基于值构造函数构建类型保护。

But before moving on to discuss subtypes, there is a small improvement we can implement to our nominal type interface. Since all our nominal types share the same properties, we can abstract these away in a generic NominalType interface as follows:

但是在继续讨论子类型之前,我们可以对名义类型接口进行一些小的改进。 由于我们所有的标称类型都共享相同的属性,因此可以在通用的NominalType接口中将它们抽象化,如下所示:

Image for post

One tip that I’d like to share in case you are implementing nominal types in a package that you will publish— say on npm — is to add a level of scoping to your interface to avoid conflicts with other libraries, you can do that like this:

如果您要在要发布的包中实现名义类型(例如在npm上),我想分享的一个技巧是在您的界面中添加一定范围的范围以避免与其他库冲突,您可以这样做这个:

Image for post

TS中的标称亚型 (Nominal subtypes in TS)

There are a couple of patterns that I follow when modeling type-subtype relationships, depending on a number of factors, including but not limited to:

在对类型-子类型关系进行建模时,我会遵循几种模式,具体取决于许多因素,包括但不限于:

  • How VS’s code tooltip represents that type — Sometimes the tooltip skips the hierarchy of types when using thetype keyword and so I might use the interface keyword instead of type to solve this issue — .

    VS的代码工具提示如何表示该类型-有时,在使用type关键字时,该工具提示会跳过类型的层次结构,因此我可以使用interface关键字而不是type来解决此问题-。

  • Do I need the type just to eliminate the repetition of writing the same tagged union over and over again? Am I exposing more functions that operate on subtypes than the parent type itself?

    我是否需要这种类型只是为了消除一次又一次写相同标签的联合的重复? 与父类型本身相比,我是否公开了更多对子类型进行操作的函数?

The first pattern is where the type itself is modeled as a union type and its subtypes as independent nominal types. Let’s say we want to implement a color type, now there are many “types” of colors, hex, rgb, rgba, hsl, hsla, color names, etc….

第一种模式是将类型本身建模为联合类型,并将其子类型建模为独立的标称类型。 假设我们要实现一种颜色类型,现在有许多颜色的“类型”,例如十六进制,rgb,rgba,hsl,hsla,颜色名称等。

For the sake of simplicity, we will only support two types of colors: rgb and rgba. We can model this the following way:

为了简单起见,我们将仅支持两种颜色: rgbrgba 。 我们可以通过以下方式对此进行建模:

Image for post

For this pattern, we can create type guards based on the name of the type as follows:

对于此模式,我们可以根据类型名称创建类型防护,如下所示:

Image for post

Another pattern is using an interface with a type parameter to specify the subtype, like the following:

另一种模式是使用带有类型参数的接口来指定子类型,如下所示:

Image for post

Here, we use Color<'RGB'> and Color<'RGBA'> to represent subtypes RGB and RGBA respectively, and use Color without a type parameter to accept both. Using this pattern, we can implement type guards based on the value of valueConstructor instead of name

在这里,我们使用Color<'RGB'>Color<'RGBA'>分别表示RGBRGBA子类型,并使用不带类型参数的Color接受两者。 使用此模式,我们可以基于valueConstructor的值而不是name来实现类型保护

Image for post

Thanks for reading. I hope this was helpful. If you have any thoughts or questions, please feel free to leave a response, it might always teach someone something new :)

谢谢阅读。 我希望这可以帮到你。 如果您有任何想法或问题,请随时回复,它可能总是会教给别人一些新的东西:)

If it doesn’t make sense, keep remodeling it until it does

如果没有意义,请继续对其进行重塑,直到它有意义为止

翻译自: https://levelup.gitconnected.com/nominal-typing-in-typescript-c712e7116006

无比打字与拼英打字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值