feng xiaohan

基础类型

布尔值

let isDone: boolean = false;
let isDoneNow: boolean = true;

数字

let deLiteral: number = 1;
let hexLiteral: number = 0xf00d; // 十六进制
let binaryLiteral: number = 0b1010; // 二进制
let octalLiteral: number = 0o744; // 八进制

字符串

let studentName: string = "fxh";
studentName = "dfs";

let age: number = 20;
console.log(
  `I'm ${studentName}. My age is ${age + 1}. ${age > 18 ? "成年" : "未成年"}`
);

可以使用模板字符串和三元表达式进行简单的运算

数组

  • 使用[]

    let list: number[] = [1, 2, 3];
    let list0: any[] = [1, 2, 3, "sad"];
    

    注意:定义的什么类型的数组,在后面数组里就只能使用该类型的值(除非使用any

  • 使用数组泛型

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

元组

元组(Tuple)类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同

let x: [string, number];
x = ["hello", 30];

const arr: readonly [x: number, y?: boolean] = [1]; // 可以取别名来判断是否存在
type first = (typeof arr)[0]; // type给类型起一个新的别名

注意:类型和定义的值要相匹配

  • 访问一个已知索引元素,会得到正确的类型:

    console.log(x[0]); // hello
    console.log(x[1]); // 30
    
  • 访问一个越界的元素,会使用联合类型替代

    x[3] = "world"; // 字符串可以赋值给(string | number)类型
    console.log(x[3]); // world
    

    注意:这么写编辑器和进行tsc转换时会报错,但是不影响使用转换后的js运行

枚举(enum)

enum类型是对 JavaScript 标准数据类型的一个补充。使用枚举类型可以为一组数值赋予友好的名字。

enum Color {
  Red,
  Green,
  Blue,
}
let c: Color = Color.Green;

数字枚举

默认情况下,0开始为元素编号

console.log(Color);
// { '0': 'Red', '1': 'Green', '2': 'Blue', Red: 0, Green: 1, Blue: 2 }
console.log(Color.Blue);
// 2

自定义枚举

也可以手动赋值 :

enum Color {
  Red = 1,
  Green = 2,
  Blue = 4,
}

增长枚举

当定义了第一个枚举的值时,后面的枚举值如果没有设置则会从第一个设置的值开始增长。

,枚举类型可以由枚举的值得到它的名字

enum Color {
  Red = 1,
  Green,
  Blue,
}
let colorName: string = Color[2];

console.log(colorName); // Green
console.log(Color.Red); // 1
console.log(Color.Green); // 2
console.log(Color.Blue); // 3

字符串枚举

自定义设置字符串后不再具有增长枚举的特性,设置了一个值为字符串最好把所有的值都设置为字符串:

enum Color {
  red = "red",
  green = "green",
  blue = "blue",
}
console.log(Color.red); // red

异构枚举

多种类型穿插的枚举(比如说数字和字符串):

enum Color {
  red = 0,
  green = "green",
}
console.log(Color.red); // 0

注意:异构枚举不允许在数字枚举中插入字符串枚举,因为数字枚举没有办法做递增。

enum Color {
  red,
  green = "green",
  blue, // Error
}

接口枚举

通过接口和枚举混合定义使用:

enum Color {
  red = 0,
  green = "green",
}
interface A {
  blue: Color.red;
}
let obj: A = {
  red: Color.red,
};

const 枚举

const 枚举在 ts 编译的 js 代码中,会直接将值编译出来,不会将其(Types)编译为一个对象。

const enum Types {
  sucess,
  fail,
}
let code: number = 0;
if (code === Types.sucess) {
}

上述代码使用 const 枚举编译的 js 如下:

var code = 0;
if (code === 0) {
} //Types.sucess默认数字第一位为0

普通枚举:

var Types;
(function (Types) {
    Types[Types["sucess"] = 0] ="sucess";
    Types[Types["fail"] = 0] ="fail";
})(Types || Types = {});
var code =0;
if (code === Types.sucess){}

反向映射

我们可以通过 key 去读取 value,也可以通过 value 读取 key。

只有数字类型支持,字符串类型是不支持反向映射的。

any

为那些在编程阶段还不清楚类型的变量指定一个类型,让其通过编译阶段的检查。可以定义为任何类型。

let notSure: any = true;
let notSure2: any = 123;
let notSure3: any = "fxh";

let list3: any[] = [1, true, "free"];
list3[0] = "ade";
console.log(list3);

any 类型的值可以和任何类型的值进行交换赋值(赋给别人值和被赋值都可以)。

unknown

同 any 一样,可以定义为任何类型。

let a: unknown = 1;
  • unknown 类型只能赋值给 unknown 或者是 any 类型
  • unknown 类型无法读取值的任何属性(如果给一个对象{}设置 unknown,则其对象的属性是无法读取的,方法也不能调用);但是 any 类型可以。

void

没有任何类型。

函数

当一个函数没有返回值的时候,返回类型为void

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

变量

声明一个void类型的变量没有什么大用处,因为你只能为它赋予undefinednull(测试返回null时会报错,可能是因为在严格模式下)

let unusable: void = undefined;

null 和 undefined

undefinednull两者各自有自己的类型分别叫做undefinednull

let u: undefined = undefined;
let n: null = null;
  • 默认情况下nullundefined所有类型的子类型,你可以把nullundefined赋值给其他类型

    let otherValue:number = null;
    let otherValue:string = null;
    let otherValue:boolean = null;
    let otherValue:void = null;
    let otherValue:any = null;
    ....
    
  • 当你指定了--strictNullChecks标记,nullundefined只能赋值给void和它们各自。

never

表示的是那些永不存在的值的类型

注意:never 在使用联合类型时会被忽略。

  • 可以进行一些返回错误的函数:

    // 返回never的函数必须存在无法达到的终点
    function error(message: string): never {
      throw new Error(message); // 抛出错误
    }
    
    // 推断的返回值类型为never
    function fail() {
      return error("Something failed");
    }
    
    // 返回never的函数必须存在无法达到的终点
    function infiniteLoop(): never {
      while (true) {
        // 死循环
      }
    }
    

    never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。 即使 any也不可以赋值给never

    • 实际上 let num2:never = null;是可以被赋值为 null ,但 never 赋值不了任何值
  • 进行兜底逻辑的判断:

    type fruits = "apple" | "banana" | "pear";
    
    function eat(value: A) {
      switch (value) {
        case "apple":
          break;
        case "banana":
          break;
        case "pear":
          break;
        default:
          const error: never = value;
          break;
      }
    }
    

    这样如果修改了 fruits 的类型,使用 eat 时也能知道是哪里出了问题。

object

object表示所有非原始类型,也就是除numberstringbooleansymbolnullundefined之外的类型。

可以表示所有引用类型。

使用object类型,就可以更好的表示像Object.create这样的 API。例如:

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

let a: object = "123"; // Error
let a: object = 456; // Error
let a: object = false; // Error
let a: object = []; // OK
let a: object = {}; // OK
let a: object = () => 678; // ok

Object

大写的Object类型相当于原型链最顶端的 Object。它可以定义所有基础的类型。

let a: Object = 123;
let a1: Object = "123";

对象字面量

跟 Object 定义范围类似,包含所有类型,可以理解为new Object

let a: {} = 123;
let a1: {} = "456";
let a2: {} = false;
let a3: {} = [];
let a4: {} = { name: "zs" };

对象字面量进行赋值之后,无法再对该值进行修改。

小结

类型等级

  • 顶级类型:any、unknown
  • 第二大类型:Object
  • 第三大类型:Number、String、Boolean
  • 第四大类型:number、string、boolean
  • 第五大类型:123、’张三’、false(直接赋值的类型)
  • 第六大类型:never

上层类型可以覆盖下层类型。