basic-types 基础类型
# 目录
# The Basics
- Static type-checking 静态类型检查
Static types systems describe the shapes and behaviors of what our values will be when we run our programs. A type-checker like TypeScript uses that information and tells us when things might be going off the rails. 静态类型系统描述了当我们运行程序时我们的值的形状和行为。类似于打字稿的类型检查器使用这些信息,并告诉我们什么时候可能会出问题。
- Non-exception Failures 无异常错误
A static type system has to make the call over what code should be flagged as an error in its system, even if it’s “valid” JavaScript that won’t immediately throw an error. 静态类型系统必须调用系统中应该标记为错误的代码,即使它是 “有效的” JavaScript,不会立即抛出错误。
- Types for Tooling 类型工具
The type-checker has information to check things like whether we’re accessing the right properties on variables and other properties. Once it has that information, it can also start suggesting which properties you might want to use. 类型检查器有信息来检查我们是否正在访问变量和其他属性的正确属性。一旦它有了这些信息,它还可以开始建议您可能想要使用哪些属性。
tsc, the TypeScript compiler 编译器
Explicit Types 显式类型
Erased Types 被擦除的类型
Type annotations aren’t part of JavaScript (or ECMAScript to be pedantic), so there really aren’t any browsers or other runtimes that can just run TypeScript unmodified. That’s why TypeScript needs a compiler in the first place - it needs some way to strip out or transform any TypeScript-specific code so that you can run it. 类型注释不是 JavaScript 的一部分 (或者说 ECMAScript 是迂腐的) ,所以真的没有任何浏览器或者其他运行时可以不经修改就运行打字稿。这就是为什么打字稿首先需要一个编译器 —— 它需要某种方法去掉或转换任何特定于打字稿的代码,以便您可以运行它。
- Downleveling 下调水平
TypeScript has the ability to rewrite code from newer versions of ECMAScript to older ones such as ECMAScript 3 or ECMAScript 5 (a.k.a. ES3 and ES5). This process of moving from a newer or “higher” version of ECMAScript down to an older or “lower” one is sometimes called downleveling. 打字稿能够将新版本的 ECMAScript 代码重写到旧版本,如 ECMAScript 3 或 ECMAScript 5 (又名 es3 和 ES5)。从一个更新的或者 “更高” 的 ECMAScript 版本下降到一个更旧的或者 “更低” 的过程有时被称为下调。
By default TypeScript targets ES3, an extremely old version of ECMAScript. We could have chosen something a little bit more recent by using the target option. Running with --target es2015 changes TypeScript to target ECMAScript 2015, meaning code should be able to run wherever ECMAScript 2015 is supported. 默认情况下,打字稿的目标是 ES3,一个非常老的 ECMAScript 版本。通过使用 target 选项,我们可以选择一些更新的内容。使用 -- target es2015 将打字稿更改为针对 ECMAScript 2015,这意味着代码应该能够在支持 ECMAScript 2015 的任何地方运行。
While the default target is ES3, the great majority of current browsers support ES2015. Most developers can therefore safely specify ES2015 or above as a target, unless compatibility with certain ancient browsers is important. 虽然默认的目标是 ES3,但是大多数当前的浏览器都支持 ES2015。因此,大多数开发人员可以安全地将 es2015 或以上指定为目标,除非与某些古老浏览器的兼容性很重要。
- Strictness 严格
In contrast, a lot of users prefer to have TypeScript validate as much as it can straight away, and that’s why the language provides strictness settings as well. These strictness settings turn static type-checking from a switch (either your code is checked or not) into something closer to a dial. The further you turn this dial up, the more TypeScript will check for you. This can require a little extra work, but generally speaking it pays for itself in the long run, and enables more thorough checks and more accurate tooling. When possible, a new codebase should always turn these strictness checks on. 相比之下,很多用户更喜欢让 TypeScript 尽可能直接地进行验证,这就是为什么该语言也提供了严格的设置。这些严格的设置将静态类型检查从开关 (无论您的代码是否被检查) 转变为更接近于刻度盘的设置。你拨号拨得越远,越多的打字稿会为你检查。这可能需要一些额外的工作,但一般来说,从长远来看,这样做是值得的,并且可以进行更彻底的检查和更精确的工具。如果可能的话,一个新的代码库应该总是启用这些严格的检查。
The strict flag in the CLI, or "strict": true in a tsconfig.json toggles them all on simultaneously, but we can opt out of them individually. The two biggest ones you should know about are noImplicitAny and strictNullChecks. CLI 中的严格标志,或者说 “strict”: 在 tsconfig.json 中为 true,可以同时开启所有选项,但是我们可以单独选择退出。你应该知道的两个最重要的检查是 noImplicitAny 和 strictnullcheck。
# Everyday Types 日常类型
- The primitives: string,number, and boolean
- Arrays 数组
- any
- Functions
- Anonymous Functions 匿名函数
- Object Types 对象类型
- Optional Properties 可选属性
- Union Types 合并类型
- Type Aliases 类型别名
- Interfaces 接口
- Type Assertions 类型断言
TypeScript only allows type assertions which convert to a more specific or less specific version of a type. 打字稿只允许类型断言转换为更具体或更不具体的类型版本。
Sometimes this rule can be too conservative and will disallow more complex coercions that might be valid. If this happens, you can use two assertions, first to any (or unknown, which we’ll introduce later), then to the desired type. 有时这个规则可能过于保守,不允许更复杂的有效强制。如果出现这种情况,您可以使用两个断言,首先是针对 any (或者我们将在后面介绍的 unknown) ,然后是所需的类型。
- Literal Types 文字类型
- Literal Inference 字面推理
The as const suffix acts like const but for the type system, ensuring that all properties are assigned the literal type instead of a more general version like string or number. As const 后缀的作用类似于 const,但是对于类型系统,确保所有属性都被分配为文本类型,而不是字符串或数字之类的更一般的版本。
- null and undefined
- Enums
- Less Common Primitives technique 不太常见的原语:bigint、symbol
# Narrowing 缩小范围
- typeof type guards
"string"、"number"、"bigint"、"boolean"、"symbol"、"undefined"、"object"、"function"
- Truthiness narrowing
- Equality narrowing
- The in operator narrowing
- instanceof narrowing
- Assignments 工作分配
- Control flow analysis 控制流分析
- Using type predicates 使用类型谓词
A predicate takes the form parameterName is Type, where parameterName must be the name of a parameter from the current function signature. 谓词接受表单 parameterName is Type,其中 parameterName 必须是来自当前函数签名的参数的名称。
classes can use this is Type to narrow their type. 此外,类可以使用 this is Type 来缩小它们的类型。
Discriminated unions 消除联合类型
The never type
When narrowing, you can reduce the options of a union to a point where you have removed all possibilities and have nothing left. In those cases, TypeScript will use a never type to represent a state which shouldn’t exist. 当缩小范围时,您可以将联合的选项减少到删除了所有的可能性并且没有剩余的选项。在这些情况下,TypeScript 将使用一个 never 类型来表示一个不应该存在的状态。
- Exhaustiveness checking 彻底检查
The never type is assignable to every type; however, no type is assignable to never (except never itself). This means you can use narrowing and rely on never turning up to do exhaustive checking in a switch statement. Never 类型可以分配给每个类型;但是,没有任何类型可以分配给 never (除了它本身)。这意味着您可以在 switch 语句中使用收缩,并依赖于永远不会进行详尽的检查。
# More on Functions
- Function Type Expressions 函数类型表达式
- Call Signatures 调用签名
In JavaScript, functions can have properties in addition to being callable. However, the function type expression syntax doesn’t allow for declaring properties. If we want to describe something callable with properties, we can write a call signature in an object type. 在 JavaScript 中,函数除了可调用之外,还可以具有属性。但是,函数类型表达式语法不允许声明属性。如果我们想用属性来描述可调用的东西,我们可以用对象类型来写一个调用签名.
type DescribableFunction = {
description: string;
(someArg: number): boolean;
};
function doSomething(fn: DescribableFunction) {
console.log(fn.description + " returned " + fn(6));
}
2
3
4
5
6
7
- Construct Signatures 构造签名
JavaScript functions can also be invoked with the new operator. TypeScript refers to these as constructors because they usually create a new object. You can write a construct signature by adding the new keyword in front of a call signature: 函数也可以用新的操作符来调用。引用这些作为构造函数,因为它们通常会创建一个新对象。你可以通过在调用签名前面添加 new 关键字来写一个构造签名:
type SomeConstructor = {
new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
return new ctor("hello");
}
2
3
4
5
6
Some objects, like JavaScript’s Date object, can be called with or without new. You can combine call and construct signatures in the same type arbitrarily: 有些对象,比如 JavaScript 的 Date 对象,可以使用或不使用 new 来调用。您可以任意组合调用和构造同一类型的签名:
interface CallOrConstruct {
new (s: string): Date;
(n?: number): number;
}
2
3
4
- Generic Functions 泛型函数
In TypeScript, generics are used when we want to describe a correspondence between two values. 在 TypeScript 中,泛型用于描述两个值之间的对应关系。
- Inference 推断
- Constraints 约束
Sometimes we want to relate two values, but can only operate on a certain subset of values. In this case, we can use a constraint to limit the kinds of types that a type parameter can accept. 有时候我们想要关联两个值,但是只能对值的某个子集进行操作。在这种情况下,我们可以使用约束来限制类型参数可以接受的类型种类。
function longest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length >= b.length) {
return a;
} else {
return b;
}
}
2
3
4
5
6
7
Working with Constrained Values 使用约束值
Specifying Type Arguments 指定类型参数
Guidelines for Writing Good Generic Functions 编写良好通用函数的指南
Push Type Parameters Down 下推类型参数
Rule: When possible, use the type parameter itself rather than constraining it 规则:如果可能的话,使用类型参数本身而不是约束它
Use Fewer Type Parameters 使用更少的类型参数
Rule: Always use as few type parameters as possible 规则:总是使用尽可能少的类型参数
Type Parameters Should Appear Twice 类型参数应该出现两次
Rule: If a type parameter only appears in one location, strongly reconsider if you actually need it 规则:如果一个类型参数只出现在一个位置,请强烈重新考虑是否实际需要它
Optional Parameters 可选参数
Function Overloads 函数重载
In TypeScript, we can specify a function that can be called in different ways by writing overload signatures. To do this, write some number of function signatures (usually two or more), followed by the body of the function: 在打字稿中,我们可以通过写重载签名来指定一个可以以不同方式调用的函数。要做到这一点,写一些函数签名 (通常是两个或更多) ,后面跟着函数体:
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
2
3
4
5
6
7
8
9
- Writing Good Overloads 写好重载
Always prefer parameters with union types instead of overloads when possible 如果可能的话,总是倾向于使用联合类型的参数,而不是重载
- Other Types to Know About 其他需要了解的类型
void:
In JavaScript, a function that doesn’t return any value will implicitly return the value undefined. However, void and undefined are not the same thing in TypeScript. 在 JavaScript 中,不返回任何值的函数将隐式返回未定义的值。然而,void 和 undefined 在打字稿中并不是一回事。
object:
The special type object refers to any value that isn’t a primitive (string, number, bigint, boolean, symbol, null, or undefined). This is different from the empty object type { }, and also different from the global type Object. It’s very likely you will never use Object. 特殊类型对象引用任何不是基元的值 (string、 number、 bigint、 boolean、 symbol、 null 或 undefined)。这不同于空对象类型 {} ,也不同于全局类型 Object。很有可能你永远不会使用 Object。
object is not Object. Always use object! 对象不是对象。始终使用对象!
unknown:
The unknown type represents any value. This is similar to the any type, but is safer because it’s not legal to do anything with an unknown value. 未知类型表示任何值。这类似于任何类型,但是更安全,因为任何未知值都是不合法的。
never:
The never type represents values which are never observed. In a return type, this means that the function throws an exception or terminates execution of the program. Never 类型表示从未观察到的值。在返回类型中,这意味着函数抛出异常或终止程序的执行。
never also appears when TypeScript determines there’s nothing left in a union. 当打字稿确定工会中没有剩余的内容时,也不会出现。
Function:
The global type Function describes properties like bind, call, apply, and others present on all function values in JavaScript. It also has the special property that values of type Function can always be called; these calls return any. 全局类型 Function 描述了类似 bind、 call、 apply 等属性,这些属性出现在 JavaScript 中的所有函数值上。它还有一个特殊属性,即 Function 类型的值总是可以被调用;这些调用返回任何。
This is an untyped function call and is generally best avoided because of the unsafe any return type. 这是一个非类型化的函数调用,通常最好避免这种情况,因为任何返回类型都是不安全的。
If you need to accept an arbitrary function but don’t intend to call it, the type () => void is generally safer. 如果您需要接受一个任意函数,但不打算调用它,那么 type () => void 通常更安全。
Rest Parameters and Arguments
Parameter Destructuring 参数析构
Assignability of Functions 函数的可转让性
Return type void:
Contextual typing with a return type of void does not force functions to not return something. Another way to say this is a contextual function type with a void return type (type vf = () => void), when implemented, can return any other value, but it will be ignored. 返回类型为 void 的上下文类型不会强制函数不返回某些内容。另一种方法是使用 void 返回类型 (type vf = () = > void) 的上下文函数类型,实现后可以返回任何其他值,但是它将被忽略。
And when the return value of one of these functions is assigned to another variable, it will retain the type of void. 当其中一个函数的返回值被赋给另一个变量时,它将保留 void 类型。
There is one other special case to be aware of, when a literal function definition has a void return type, that function must not return anything. 还有另外一个需要注意的特殊情况,当文本函数定义具有 void 返回类型时,该函数不能返回任何内容。
# Object Types 对象类型
Property Modifiers 属性修饰符
Optional Properties 可选属性
Note that there is currently no way to place type annotations within destructuring patterns. This is because the following syntax already means something different in JavaScript. 请注意,目前没有将类型注释放置在析构化模式中的方法。这是因为下面的语法在 JavaScript 中已经有了不同的含义。
- readonly Properties
Properties can also be marked as readonly for TypeScript. While it won’t change any behavior at runtime, a property marked as readonly can’t be written to during type-checking. 属性也可以标记为 TypeScript 的只读属性。虽然它不会在运行时改变任何行为,但是在类型检查期间不能写入标记为 readonly 的属性。
Using the readonly modifier doesn’t necessarily imply that a value is totally immutable - or in other words, that its internal contents can’t be changed. It just means the property itself can’t be re-written to. 使用 readonly 修饰符并不一定意味着一个值是完全不可变的,或者换句话说,它的内部内容不能被更改。这只是意味着财产本身不能被重写。
- Index Signatures 索引签名
An index signature property type must be either ‘string’ or ‘number’. 索引签名属性类型必须是 “string” 或 “ number”。
While string index signatures are a powerful way to describe the “dictionary” pattern, they also enforce that all properties match their return type. This is because a string index declares that obj.property is also available as obj["property"]
.
虽然字符串索引签名是描述 “字典” 模式的一种强大方式,但是它们也要求所有属性都匹配它们的返回类型。这是因为字符串索引声明 obj.property 也可以作为 obj [“ property”] 使用。
you can make index signatures readonly in order to prevent assignment to their indices. 您可以使索引签名只读,以防止分配给他们的索引。
interface ReadonlyStringArray {
readonly [index: number]: string;
}
2
3
Extending Types 扩展类型
Intersection Types 交叉类型
Interfaces vs. Intersections
We just looked at two ways to combine types which are similar, but are actually subtly different. With interfaces, we could use an extends clause to extend from other types, and we were able to do something similar with intersections and name the result with a type alias. The principle difference between the two is how conflicts are handled, and that difference is typically one of the main reasons why you’d pick one over the other between an interface and a type alias of an intersection type. 我们刚刚研究了两种组合类型的方法,这两种类型相似,但实际上略有不同。对于接口,我们可以使用 extends 子句从其他类型进行扩展,而且我们可以对交叉点进行类似的操作,并使用类型别名命名结果。两者之间的主要区别在于如何处理冲突,这种区别通常是在接口和交集类型的类型别名之间选择一个而不是另一个的主要原因之一。
Generic Object Types 泛型对象类型
The Array Type
The ReadonlyArray Type
The ReadonlyArray is a special type that describes arrays that shouldn’t be changed. ReadonlyArray 是一种特殊类型,用于描述不应该更改的数组。
Much like the readonly modifier for properties, it’s mainly a tool we can use for intent. When we see a function that returns ReadonlyArrays, it tells us we’re not meant to change the contents at all, and when we see a function that consumes ReadonlyArrays, it tells us that we can pass any array into that function without worrying that it will change its contents. 很像属性的 readonly 修饰符,它主要是一个我们可以使用的工具意图。当我们看到一个函数返回 ReadonlyArrays 时,它告诉我们,我们根本不打算改变内容,当我们看到一个函数使用 ReadonlyArrays 时,它告诉我们,我们可以将任何数组传递到该函数,而不用担心它会改变其内容。
Just as TypeScript provides a shorthand syntax for Array<Type>
with Type[], it also provides a shorthand syntax for ReadonlyArray<Type>
with readonly Type[].
正如 TypeScript 为 Array <Type> 提供了一种简化语法,使用 Type [] ,它也为 ReadonlyArray < Type > 提供了一种简化语法,使用 readonly Type []。
- Tuple Types 元组类型
A tuple type is another sort of Array type that knows exactly how many elements it contains, and exactly which types it contains at specific positions. Tuple 类型是另一种 Array 类型,它确切地知道它包含多少个元素,以及它在特定位置包含哪些类型。
Another thing you may be interested in is that tuples can have optional properties by writing out a question mark (? after an element’s type). Optional tuple elements can only come at the end, and also affect the type of length. 您可能感兴趣的另一件事是,通过写出一个问号 (?在元素的类型之后)。可选的 tuple 元素只能出现在结尾,并且还会影响长度的类型。
Tuples can also have rest elements, which have to be an array/tuple type. 元组还可以有 rest 元素,这些元素必须是数组 / 元组类型。
type Either2dOr3d = [number, number, number?];
type StringNumberBooleans = [string, number, ...boolean[]];
type StringBooleansNumber = [string, ...boolean[], number];
type BooleansStringNumber = [...boolean[], string, number];
2
3
4
A tuple with a rest element has no set “length” - it only has a set of well-known elements in different positions. 带有 rest 元素的 tuple 没有设置 “长度”—— 它只有一组位于不同位置的已知元素。
- readonly Tuple Types 元组类型
# modules 模块
# Non-modules 非模块
The JavaScript specification declares that any JavaScript files without an export or top-level await should be considered a script and not a module. JavaScript 规范声明,任何没有导出或顶级等待的 JavaScript 文件都应该被视为脚本,而不是模块。
# CommonJS and ES Modules interop 和 ES 模块互操作
There is a mis-match in features between CommonJS and ES Modules regarding the distinction between a default import and a module namespace object import. TypeScript has a compiler flag to reduce the friction between the two different sets of constraints with esModuleInterop.
关于默认导入和模块名称空间对象导入之间的区别,CommonJS 和 ES Modules 之间的特性不匹配。TypeScript 有一个编译器标志,以减少 esModuleInterop 中两组不同约束之间的摩擦。