TypeScript入门之数据类型

863 阅读8分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

简介

TypeScript中定义变量的时候需要指定变量的数据类型。

数据类型我们需要使用小写形式,也就是boolean、number、string,不要写成了Boolean、Number、String这种。

Boolean、Number、StringJavaScript 的构造函数,比如我们用 Number 用于数字类型转化或者构造 Number 对象用的。而 TypeScript 中的 number 类型仅仅是表示类型,两者完全不同。

基本简单类型

TypeScript支持js中的七种简单数据类型。

数字 number

const decLiteral: number = 6
const hexLiteral: number = 0xf00d
const binaryLiteral: number = 0b1010
const octalLiteral: number = 0o744

字符串 string

const str: string = "randy";

布尔类型 boolean

const b: boolean = true;

null

let n: null = null;

默认情况下null是只能赋值给null类型的变量的。但是当我们在tsconfig.json设置strictNullChecks: falsenull 可以赋值给任何类型的变量。

// null和undefined赋值给string
let str:string = "哈哈";
str = null
let bool1: boolean = true;
bool1 = null

undefined

let u: undefined = undefined;

默认情况下 undefined 是所有类型的子类型。就是说你可以把 undefined 赋值给其他类型。

// null和undefined赋值给string
let str:string = "哈哈";
str= undefined
let bool1: boolean = true;
bool1= undefined

symbol

const sym: symbol = Symbol("name");

bigint

使用 BigInt 需要在 tsconfig.json 中给 lib 选项添加 "ESNext"

const big: bigint = BigInt("1111111111111111");

TypeScript中,number 类型虽然和 BigInt 都是有表示数字的意思,但是实际上两者类型是不同的:

let foo: number;
let bar: bigint;

foo = bar; // error: Type 'bigint' is not assignable to type 'number'.
bar = foo; // error: Type 'number' is not assignable to type 'bigint'.

复杂数据类型

object

object 表示非原始类型,也就是除 number,string,boolean,symbol,null,undefined 之外的类型。

// 对象类型
const user: {
  name: string;
  age: number;
} = { name: "randy", age: 25 };

// 类
class Person {}

const myPeople: Person = new Person();

js中是一样的,引用类型都可以是object类型

let value: object
value = new Date()
value = [1]
value = [1, 'hello']

数组 number[] 或者 Array<number>

这里的 number 只是举个例子,可以有其他类型比如 string、any 等。

const arr1: number[] = [1, 2, 3];
const arr2: Array<number> = [4, 5, 6];

// 这里用到了联合类型,后面会说
const arr3: (string | number)[] = [123, "randy"];
const arr4: Array<string | number> = [456, "demi"];

// 存对象
const arr5: { name: string; age: number }[] = [{ name: "randy", age: 25 }];

// 或者使用类型别名 type
type User = { name: string; age: number };
const arr6: User[] = [{ name: "demi", age: 25 }];

// 二维数组
const erweiArr: [][] = [
  [1, 2, 3],
  [4, 5, 6],
];

元组 Tuple

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同,但是顺序个数不能变。

let x: [string, number];

// 这样是可以的
x = ["hello", 10];

// 这样是错的
x = [10, 'hello']

枚举 enum

枚举 enum 类型是对 JavaScript 标准数据类型的一个补充。

enum Color {
  Red,
  Green,
  Blue,
}

//返回的是下标 类似数组下标从 0 开始 也可以赋初始值 Red=10 等这样返回的就是 11
let c1: Color = Color.Red;
console.log(c1); // 0
let c2: Color = Color.Green;
console.log(c2); // 1

// 我们还可以通过下标访问
console.log(Color[0] === "Red"); // true
console.log(Color[1] === "Green"); // true

我们还可以设置枚举的值是字符串,但是设置之后,通过下标的方式就获取不到值了。

enum Direction {
  LEFT = "left",
  RIGHT = "right",
}
console.log(Direction.LEFT); // left
console.log(Direction.RIGHT); // right

console.log(Direction[0]); //undefined
console.log(Direction[1]); //undefined

any

我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。那么我们可以使用 any 类型来标记这些变量。

变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型。

let notSure: any = 72;
notSure = "maybe a string instead";

记住any类型是多人协作项目的大忌,很可能把Typescript变成AnyScript,通常在不得已的情况下,不应该首先考虑使用此类型。

unknown

unknownTypeScript 3.0 引入了新类型,是 any 类型对应的安全类型。

虽然它们都可以是任何类型,但是当 unknown 类型被确定是某个类型之前,它不能被进行任何操作比如实例化、getter、函数执行等等。

let value: any;

value = true;             // OK
value = 1;                // OK
value = "Hello World";    // OK
value = Symbol("type");   // OK
value = {}                // OK
value = []                // OK

let value2: unknown;

value = true;             // OK
value = 1;                // OK
value = "Hello World";    // OK
value = Symbol("type");   // OK
value = {}                // OK
value = []                // OK

let value3: any;

value3.foo.bar;  // OK
value3();        // OK
new value3();    // OK
value3[0][1];    // OK

let value4: unknown;

value4.foo.bar;  // ERROR
value4();        // ERROR
new value4();    // ERROR
value4[0][1];    // ERROR

void

void 申明变量或函数。

当一个函数没有返回值时,你可以申明类型为 void

// 没有返回值的函数
function sayName(): void {
  console.log("randy");
}

当变量申明为 void 的时候只能为它赋予 undefined

const u: void = undefined;

当然,当我们在tsconfig.json设置strictNullChecks: falsenull 可以赋值给任何类型的变量。也就可以赋值给void类型的变量。

const n: void = null;

never

never 类型表示的是那些永不存在的值的类型。用得少(死循环或者抛出异常)

function whileTrueFun(): never {
  while (true) {}
}

function throwErrorFun(): never {
  throw new Error("自定义错误呢");
}

// 空数组,而且永远是空的
const empty: never[] = []

高级类型

联合类型 |

TypeScript 不确定一个变量类型的时候可以使用联合类型。使用|定义。

但是我们只能访问此联合类型的所有类型里共有的属性或方法。

类似js里面或的意思,就是多种类型中选择一种。

let myFavoriteNumber: string | number = 123;

myFavoriteNumber = "randy";

交叉类型 &

交叉类型是将多个类型合并为一个类型。通过 & 定义。

类似js里面与的意思,就是多种类型的结合。

type Flag1 = { x: number };
type Flag2 = { y: string };
type Flag3 = Flag1 & Flag2;

let flag: Flag3 = {
  x: 1,
  y: "hello",
};

// 接口也支持
interface User1 {
  name: string;
}

interface User2 {
  age: number;
}

type User3 = User1 & User2;

const user: User3 = { name: "randy", age: 24 };
console.log(user);

字面量类型

TypeScript 中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。 目前,TypeScript 支持 3 种字面量类型:字符串字面量类型、数字字面量类型、布尔字面量类型,对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型,具体示例如下:

let flag1: "hello" = "hello";
let flag2: 1 = 1;
let flag4: true = true;

虽然可以定义字面量类型,但是它的值却不能改变了,那这个字面量类型有啥用呢?

// 定义好之后就不能改变值了

// flag1 = 'randy' // error 不能将类型“"randy"”分配给类型“"hello"”。
// flag2 = 2 // error 不能将类型“2”分配给类型“1”
// flag4 = false // error 不能将类型“false”分配给类型“true”

字面量类型它真正的应用场景是可以把多个字面量类型组合成一个联合类型,用来描述拥有明确成员的实用的集合。

比如

type Direction2 = 'up' | 'down' ;

function move(dir: Direction2) {
  // ...
}
move('up'); // ok
move('right'); // 类型“"right"”的参数不能赋给类型“Direction2”的参数

通过使用字面量类型组合的联合类型,我们可以限制函数的参数为指定的字面量类型集合,然后编译器会检查参数是否是指定的字面量类型集合里的成员。

因此,相较于使用 string 类型,使用字面量类型(组合的联合类型)可以将函数的参数限定为更具体的类型。这不仅提升了程序的可读性,还保证了函数的参数类型,可谓一举两得。

有没有感觉有点像简单版的枚举类型,哈哈。

条件类型

条件类型够表示非统一的类型,以一个条件表达式进行类型关系检测,从而在两种类型中选择其一:

T extends U ? X : Y

上面的代码可以理解为: 若 T 能够赋值给 U,那么类型是 X,否则为 Y,有点类似于JavaScript中的三元条件运算符。

比如我们声明一个函数 f,它的参数接收一个布尔类型,当布尔类型为 true 时返回 string 类型,否则返回 number 类型。

declare function f<T extends boolean>(x: T): T extends true ? string : number;

const x = f(Math.random() < 0.5)
const y = f(false)
const z = f(true)

 x y z 的类型分别如下:

image.png

image.png

image.png

对于extends如果不熟悉的话可以先跳过,笔者后面讲泛型约束的时候会详细介绍。

系列文章

TypeScript入门之环境搭建

TypeScript入门之数据类型

TypeScript入门之函数

TypeScript入门之接口

TypeScript入门之类

TypeScript入门之类型推断、类型断言、双重断言、非空断言、确定赋值断言、类型守卫、类型别名

TypeScript入门之泛型

TypeScript入门之装饰器

TypeScript入门之模块与命名空间

TypeScript入门之申明文件

TypeScript入门之常用内置工具类型

TypeScript入门之配置文件

后记

感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!