Boolean

Boolean 是最基础的数据类型之一,即是我们最常见的:true、false

我们在js中定义boolean类型数据的时候往往是这么书写的:

  1. let bool = true;

在ts中,我们可以尝试这么书写:

  1. let bool: boolean = true;

这个时候,可能会有聪明的小伙伴会问了,我可不可以通过new构造函数来生成一个Booleanodgar数据呢?

象这样写?

  1. let des: Boolean = new Boolean(1)
  2. //Don't use 'Boolean' as a type. Avoid using the `Boolean` type. Did you mean `boolean`? (ban-types)tslint(1)

不难发现,编译器在给我们报错了,我们或许可以这样来改造它

  1. let des: Boolean = new Boolean(1)
  2. //Forbidden constructor, use a literal or simple function call instead (no-construct)
  3. console.log(des) //Boolean {true}
  4. console.log(bool === des) //false
  5. console.log(bool === des) //true

尽管编译通过了,但是似乎并没有通过tslint的检测

  1. let des boolean = Boolean(1);
  2. console.log(des === bool) //true

它与 let xxx: boolean = true/false 是一样的

在以上示例中,我们可以看到 : 后面有 booleanBoolean 两中不一样的约定,在这里需要简单的描述一下, boolean 是数据类型, Boolean 是构造函数


Number

和JS一样,TS内部所有的数据均是浮点型的数字,呈现这些浮点数的数据类型是 Number ,TS支持JS中Number数据类型所支持的二进制、八进制、十六进制字面量。

这是我们在JS中的写法

  1. let num = 123

在TS中,我们可以这么定义:

  1. let num: number = 123; //十进制
  2. let num1: number = 0b10; // 二进制
  3. let num2: number = 0B10; // 二进制
  4. let num3: number = 0o10; // 八进制
  5. let num4: number = 0O10; // 八进制
  6. let num5: number = 0x11; // 十六进制
  7. let num6: number = 0X11; // 十六进制
  8. let num7: number = NaN; // NaN
  9. let num8: number = Infinity; // 无穷
  10. let num9: number = -Infinity; // 负无穷

String

和JS一样,TS也支持 `` 和${}的使用,但是建议在TS中定义字符串的时候尽量在最外层使用而不是‘`

  1. let Name: string = "bob";
  2. let age: number = 24;
  3. let sense: string = `Hello, my name is ${Name},I am ${age} years old`;

Array

TS与JS一样,均可以操作数组元素,在TS中定义数组的方式有以下两种:

  1. 通过在数据类型后接上 []

    1. let list: number[] = [1, 2, 3];
  2. 通过数组泛型的方法(此种方法在使用tslint的初始配置时会默认转化成第一种方法)

    1. let list: Array<number> = [1, 2, 3];

同样地,es6中支持的对数组的操作,在TS中也均是支持的。
举个小粟子:

  1. let list: number[] = [1, 2, 3];
  2. let list2 = [2, 2, ...list];
  3. console.log(list2); //[2,2,1,2,3]
  4. console.log(Reflect.keys(list)); //[0,1,2]
  5. console.log(Reflect.values(list)); //[1,2,3]
  6. console.log(list instanceof Array); //true

Tuple

元组类型(Tuple)允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
直接举个粟子:

  1. let x: [string, number];
  2. x = ["okk", 20];
  3. console.log(x instanceof Array); //true

在进行元组的赋值时,需要注意的是,我们赋的值首先需要符合定义的数据类型以及数量,缺少或者不符都会报错。

  1. let x: [string, number];
  2. x = ["okk"];
  3. //Property '1' is missing in type '[string]' but required in type '[string, number]'.
  4. x = ["okk", "Ok"];
  5. //不能将类型“string”分配给类型“number”。

在部分教程可以看到,如果我们实在是需要只给其中的一个元素赋值,可以这么做

  1. let names: [string, number];
  2. names[0] = 'name';
  3. //在赋值前使用了变量“names”。

经过实际操作证明了,我们不可以这样为一个元组进行初始化赋值的操作,但是,我们可以在初始化之后进行这种操作

  1. let names: [string, number];
  2. names = ["zxc", 24];
  3. names[0] = 'name';

有的时候,我们会不满足于仅使用我们定义的两个数据,我们需要向其中添加跨界元素来使用

  1. let names: [string, number];
  2. names = ["zxc", 24];
  3. names.push(163);
  4. names.push(false);
  5. //类型“false”的参数不能赋给类型“string | number”的参数。

我们添加的跨界元素的类型必须是已经在元素定义时使用过的元素类型之一,才可以进行添加。

另外纠正某些中文文档上未曾更改的错误,请勿使用其提供的方式来进行跨界元素的添加,行不通!

  1. let names: [string, number];
  2. names = ["zxc", 24];
  3. names[3] = "word"
  4. //不能将类型“"word"”分配给类型“undefined”。
  5. //Tuple type '[string, number]' of length '2' has no element at index '3'.

Enum

enum 类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。

  1. enum code {bad= 200, ok= 100, do= 0}
  2. let c: code = code.bad; //等同于 let c: code = code["bad"];
  3. console.log(c); //200

乍一看好象是一个对象的异种
其实不然,来举几个粟子,通过这几个粟子来了解一下枚举

  1. enum Status {one, two, three, four};

这种,我们什么都不做的情况下,它会被默认赋值从0开始的数据,同时与枚举名反向映射

我们可以这么理解

  1. console.log(Status["one"] === 0); // true
  2. console.log(Status["two"] === 1); // true
  3. console.log(Status["three"] === 2); // true
  4. console.log(Status["four"] === 3); // true
  5. console.log(Status[0] === "one"); // true
  6. console.log(Status[1] === "two"); // true
  7. console.log(Status[2] === "three"); // true
  8. console.log(Status[3] === "four"); // true

如果我们仅对其中的部分数据进行手动赋值

  1. enum Status {one, two=4, three, four};
  2. console.log(Status["one"]); //0
  3. console.log(Status["two"]); //4
  4. console.log(Status["three"]); //5
  5. console.log(Status["four"]); //6

可以看到,其后的值是依次递增的,并且step是1

如果其中某个枚举名对就的数值是一个表达式?

  1. enum Status {one, two=4, three, four="name".length};
  2. console.log(Status["one"]); //0
  3. console.log(Status["two"]); //4
  4. console.log(Status["three"]); //5
  5. console.log(Status["four"]); //4
  6. console.log(Status[4] === "two"); // false
  7. console.log(Status[4] === "four"); // true

此时,是因为two先等于4,回后,four又等于了4,将先前的two给覆盖了,同时我们需要注意的是,使用这种方法得到枚举值的话,只能将其放在尾部

枚举值可以是非数字吗?

  1. enum Status {one, two=4, three, four= "four" as any};

答案是 yes! 注意了,这里不能是string


Any

有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量:

  1. let notSure: any = 4;
  2. notSure = "maybe a string instead";
  3. notSure = false;

any 类型在对现有代码进行改写的时候是十分凑效的,它可以允许在进入和编译的过程中退出类型检查。

  1. let suer: any;
  2. suer = "may be is String";
  3. suer = 4;

在这里指出官网的一处描述:

You might expect Object to play a similar role, as it does in other languages. However, variables of type Object only allow you to assign any value to them. You can’t call arbitrary methods on them, even ones that actually exist: 即:你可能认为Object有相似的作用,就像它在其它语言中那样。 但是Object类型的变量只是允许你给它赋任意值 - 但是却不能够在它上面调用任意的方法。

但是,经过实际操作:

  1. let suers: Object = 4;
  2. console.log(Reflect.getPrototypeOf(suers));
  3. //Uncaught TypeError: Reflect.getPrototypeOf called on non-object
  4. // at Object.getPrototypeOf (<anonymous>)

我们在检测这个“对象”的原型的时候,出现这种错误,说明,这样的一个写法,并不是一个得到的一个对象。
回头看看上面在提到Boolean的时候, : Object 这里的 Object 不同于 :object 它是一个构造函数。
所以并不建议使用这种写法,尽管这种方法在编译的时候是可以通过的,但是并不能通过tslint检测。

当只知道一组数据的部分数据类型时,可以使用 any 来定义一个数组

  1. let list: any[] = ["name", "age", 168];

Void

某种程度上来说, void 类型像是与 any 类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void

  1. function warnUser(): void {
  2. console.log("This is my warning message");
  3. }
  4. warnUser();

声明类型的变量void没有用,因为只能分配null(仅在--strictNullChecks(严格空值模式)未指定的情况下,请参阅下一节)或undefined分配给它们:

  1. let unusable: void = undefined;
  2. let unusabled: void = null; //不能将类型“null”分配给类型“void”。"(此时开启严格空值模式)

严格空值模式一般设置在tsconfig.json内 strictNullChecks:true 这样就是开启了,想要将其关闭,可以设置为false


Null && Undefined

TypeScript中,undefined和null两者各自有自己的类型分别叫做undefined和null。

  1. let u: undefined;
  2. let n: null = null;

默认情况下,null和undefined是所有其它类型的子类型
然而,当你在 tsconfig.json 中指定了 "strictNullChecks" = true 时, nullundefined 只能赋值给 void 和它们各自本身。 这能避免很多常见的问题。 也许在某处你想传入一个 stringnullundefined ,你可以使用联合类型 string | null | undefined


Never

never 类型表示永远不存在值的类型,一般用于错误处理函数。
never 类型可以是任意类型的子类型,然而任何类型均不可以赋值给 never 类型,除 never 本身外。

  1. // Function returning never must have unreachable end point
  2. function error(message: string): never {
  3. throw new Error(message);
  4. }
  5. // Inferred return type is never
  6. function fail() {
  7. return error("Something failed");
  8. }
  9. // Function returning never must have unreachable end point
  10. function infiniteLoop(): never {
  11. while (true) {
  12. console.log(1);
  13. }
  14. }

这是官方为我们提供的几个示例,可以看到,除最后一个外,上面两个均是处理异常抛出错误时会调用的。
这也验证了上文, never 类型一般用于处理错误函数

需要特别注意的是:never类型表示的是永远不存在值的类型,所以我们的迭代器控制函数是不能用用 :never 的,具体的函数相关的,包括es6中的箭头函数如何在ts中优雅地使用,将会在Function章节点详细说明。


Object

在了解TS中的 Object 类型之前,我需要了解一下一个概念:

TS中有六种原始数据类型,分别是: number string boolean symbol null undefined

object 表示的是非原始数据类型,我们使用 object 数据类型可以更好地表示 Object.xxx 这样的API,同样地,JS中的object对象的原型链上的方法在TS中一样适用。

  1. declare function create(o: object | null): void;
  2. create({ prop: 0 }); // OK
  3. create(null); // OK
  4. create(42); // Error
  5. create("string"); // Error
  6. create(false); // Error
  7. create(undefined); // Error

以上是官方给我们的例子,其中的declare声明的是一个全局函数的类型,这里暂且不讨论,以下举一个更为直观的例子:

  1. let obj: object = {};
  2. console.log(Reflect.getPrototypeOf(obj));

打印一下这个对象的原型看一下


Type assertions(类型断言)

关于类型断言,官方是这么说的:

Sometimes you’ll end up in a situation where you’ll know more about a value than TypeScript does. Usually this will happen when you know the type of some entity could be more specific than its current type. Type assertions are a way to tell the compiler “trust me, I know what I’m doing.” A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data. It has no runtime impact, and is used purely by the compiler. TypeScript assumes that you, the programmer, have performed any special checks that you need.Type assertions have two forms. One is the “angle-bracket” syntax: 大体意思就是,在某些特定的场景中,你可能比TS编译器本身更加了解你当前操作的对象应该是一个什么样的数据类型。而通过类型断言这种方式,可以更加直接清楚地告诉编译器,你的需求。
类型断言本身在不会在运行阶段作用,只会在编译阶段作用,TS假设当前代码片段已经通过了检测。

关于类型断言一般有两种表现形式,在这里更倾向于介绍使用as语法。
使用尖括号语法的时候,在经过tslint初始设置编译之后会默认将其转成as,所以相对来说,更加推荐as语法。

  1. let someValue: any = "This is a string";
  2. let strLength: number = ( someValue as string).length;
  3. let strLength: number = ( <string>someValue ).length; //等效于as语法