内容简介:本文记录两件事,一个是关于 typing 的一些名词释义,另一个便是结合 TypeScript 给出一些示例用于解释这门语言的能力。说到 typing 分类,常见的维度分为以下几种:而以上说到的最后一个分类也被用于引出 TypeScript 所采用的类型系统——结构类型系统。
A type system specifies the type rules of a programming language independently of particular typechecking algorithms. This is analogous to describing the syntax of a programming language by a formal grammar, independently of particular parsing algorithms. —— Type Systems
本文记录两件事,一个是关于 typing 的一些名词释义,另一个便是结合 TypeScript 给出一些示例用于解释这门语言的能力。
1. 关于 typing 的一些名词释义
说到 typing 分类,常见的维度分为以下几种:
- Static (expressions have types) vs. dynamic (values have types) - 静态类型和动态类型,区分的关键点为编译期或运行期确定类型:静态类型在编译期确定,动态类型在运行期确定。
- Strong (values cannot be coerced to other types without a cast) vs. weak (the runtime performs a variety of coercions for convenience) - 强类型和弱类型,区分的关键点为运行时是否自动转换到与实际类型不符的类型:强类型要求手工类型转换,弱类型自动转换。
- Latent (no type declarations) vs. manifest (type declarations) - 隐式类型和显式类型,区分的关键点为是否要在源码中声明类型:隐式类型不需要,显式类型需要。
- Nominal (subtyping relations are declared explicitly) vs. structural (subtyping relations are inferred from the operations available on types) - 标明类型和结构类型,区分的关键点为类型判定是根据标称还是根据内容:标明类型根据标称,结构类型根据内容。
而以上说到的最后一个分类也被用于引出 TypeScript 所采用的类型系统——结构类型系统。
- 结构类型系统 / Structure Type System,可以简单理解成“任两个以相同结构所描述的值的类型都是等价的”。
- 标明类型系统 / Nominal Type System,则可以简单理解成“没有两个独特的语法构成的类型表达式表示同一类型,(即类型若要相等,就必须具有相同的“名字”)”。
其他还有一些名词:
- 鸭子类型 / Duck Typing - 在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由”当前方法和属性的集合”决定。在与结构类型系统的对比上,鸭子类型和结构类型相似但与之不同。结构类型由类型的结构决定类型的兼容性和等价性,而鸭子类型只由结构中在运行时所访问的部分决定类型的兼容性。
- 泛型 / Generic - 泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型允许 程序员 在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。
关于类型系统有一本“小书”,也就几十页,但个人看起来还相当吃力,感兴趣可以移步
Cardelli, Luca. “ Type systems .” ACM Computing Surveys 28.1 (1996): 263-264.
2. 关于 TypeScript 系统性入门的一些标注
2.1TypeScript 采用结构类型系统(Structure Type System)
TypeScript 和 C# 有着颇深的渊源,他们都是在微软大神 Anders Hejlsberg 的领导之下产生的编程语言,两者在诸多设计细节方面十分相似。然而,一个非常重要的不同之处在于,C# 采用的是 Nominal Type System(标明类型系统),TypeScript 考虑到 JavaScript 本身的灵活特性,采用的是 Structural Type System。
关于标明类型系统和结构类型系统的区别,可以看这个例子。这里是一段 C# 代码:
// 示例 from https://zhuanlan.zhihu.com/p/64446259 public class Foo { public string Name { get; set; } public int Id { get; set;} } public class Bar { public string Name { get; set; } public int Id { get; set; } } Foo foo = new Foo(); // Okay. Bar bar = new Foo(); // Error!!!
Foo
和 Bar
两个类的内部定义完全一致,但是当将 Foo
实例赋值给 Bar
类型的变量时编译器报错,说明两者的类型并不一致。标明类型系统比较的是类型本身,具备非常强的一致性要求。
TypeScript 则不太一样:
// 示例 from https://zhuanlan.zhihu.com/p/64446259 class Foo { method(input: string): number { ... } } class Bar { method(input: string): number { ... } } const foo: Foo = new Foo(); // Okay. const bar: Bar = new Foo(); // Okay.
2.2TypeScript 和 JavaScript 广泛应用鸭子类型相似,只检查类型定义的约束条件
下面这个例子比较能够说明这一类型系统的灵活性:
// 示例 from https://zhuanlan.zhihu.com/p/64446259 type Point = { x: number; y: number; }; function plot(point: Point) { // ... } plot({ x: 10, y: 25 }); // Okay. plot({ x: 8, y: 13, name: 'foo' }); // Extra fields Okay. Need enable `suppressExcessPropertyError`
2.3用 TypeScript 进行类型编程
一个典型便是泛型。软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
正常情况,我们会这样定义一个函数:
function identity(arg: number): number { return arg; }
若是 arg 改变类型,那么我们的函数可能又要改写成这样:
function identity(arg: string): string { return arg; }
因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 类型变量,是一种特殊的变量,只用于表示类型而不是值,如上示例可以写成:
function identity<T>(arg: T): T { return arg; }
2.4TypeScript 提供一些 工具 类型来帮助常见的类型转换
这里举例一个有意思的类型 NonNullable,这里粘同事写的一个例子来说明:
function isNotNil<T>(x: T): x is NonNullable<T> { return x != null; } const type_guard_demo_1 = [1, 2, '', undefined, null].filter(isNotNil);
假设我们在这里不明确写上 isNotNil 的返回类型,那么 TypeScript 给你的推断结果或许就是,至少 TypeScript playground 上还是这样:
const type_guard_demo_1: (string | number | null | undefined)[]
而对返回结果加上 NonNullable 声明,便可以得到你想要的结果:
const type_guard_demo_1: (string | number)[]
NonNullable<T>
做的事情便是从类型T中剔除 null 和 undefined,然后构造一个类型。而得益于 TypeScript 本身就是用 TypeScript 开发的,你可以很容易看到 NonNullable 的实现:
/** * Exclude null and undefined from T */ type NonNullable<T> = T extends null | undefined ? never : T;
在你觉得类型不够用的时候,你还可以通过 条件类型(Conditional Type) 来创造更多的自定义工具类型。
后记
以上,是对这两部分内容的一些笔记,但这不适用于针对 TypeScript 的整体入门,因为相关内容还是欠缺太少,相关内容应该会另起篇幅书写。另外,如果你想尝试写些 TypeScript 代码, TypeScript Playground 会是一个比较不错的选择。
参考的资料与可以进一步阅读的资料包含在如下链接中:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 记录几个与quill相关的网址
- git--git tag相关命令和实践记录
- 记录一次vue练习的填坑记录
- 【错误记录】git ssh 推送失败的一次记录
- WebAssembly 相关工具
- Python 集合相关操作
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。