【TS】TypeScript 数据类型

文章目录

JS原有数据类型

1.数值类型(number)

2.字符串类型(string)

3.布尔类型(boolean)

4.null

5.undefined

6.symbol

7.数组类型(array)

【联合类型】

【自定义类型】

【多维数组】

8.函数类型(function)

【函数void类型】

【函数可选参数】

【函数剩余参数】

9.对象类型(object)

【对象可选属性】

TS新增数据类型

1.联合类型

2.自定义类型(类型别名)

3.void类型

4.any类型

【类型保护】

【污染】

5.unknown类型

6.never类型

7.元组类型

8.字面量类型

9.枚举类型(enum)

【数值枚举】

【字符串枚举】

typeof 操作符


TypeScript里的类型注解是一种轻量级的为函数或变量添加类型约束的方式。

TypeScript提供了静态的代码分析,它可以分析代码的结构和提供的类型注解。

TypeScript的类型系统可以显示标记出代码中的意外行为,从而降低发生错误的可能性。

TypeScript数据类型大致可以分为两类:JS原有数据类型TS新增数据类型

JS原有数据类型

原始数据类型:number、string、boolean、null、undefined、symbol

引用数据类型:数组、对象、函数等

1.数值类型(number)

let num: number = 1234;
num = 5678;
console.log(num); // 5678

2.字符串类型(string)

let str: string = 'hello';
str = 'world'
console.log(str); // world

3.布尔类型(boolean)

let bool: boolean = true;
bool = false;
console.log(bool); // false

4.null

let aaa: null = null;
console.log(aaa); // null

5.undefined

let bbb: undefined = undefined;
console.log(bbb); // undefined

6.symbol

let ccc: symbol = Symbol('abc');
ccc = Symbol('123');
console.log(ccc); // Symbol(123)

7.数组类型(array)

// 方式一
let arr0: number[] = [1, 2, 3, 4];
let arr1: string[] = ['苹果', '樱桃', '西瓜'];
// 方式二  泛型写法
let arr2: Array<number> = [30, 40, 50];
let arr3: Array<string> = ['北京', '上海', '郑州'];

console.log(arr0); // [1, 2, 3, 4]
console.log(arr1); // ['苹果', '樱桃', '西瓜']
console.log(arr2); // [30, 40, 50]
console.log(arr3); // ['北京', '上海', '郑州']

【联合类型】

  由两个或多个其他类型组成的类型,多个类型间使用竖线间隔,表示可以是这些类型中的任意一种。

let str0: number | boolean = true; // str0的值可以是数字或布尔类型

// 数组中既有 number 类型,又有 boolean 类型。
let arr4: (number | boolean)[] = [1, 2, true, false];
console.log(arr4); // [1, 2, true, false]

【自定义类型】

  场景:某一类型(复杂)需要多次使用。

(创建类型别名后,直接使用该类型别名作为变量的类型注解即可)

type CustomArr = (number | string)[];
let arr5: CustomArr = [1, 2, 3, 'hello'];
let arr6: CustomArr = [1, 2, 'hello', 'world'];

console.log(arr5); // [1, 2, 3, 'hello']
console.log(arr6); // [1, 2, 'hello', 'world']

【多维数组】

TypeScript 使用 Type[][] 的形式,表示二维数组,Type 是最底层数组成员的类型。

let arr: number[][] = [[1, 2, 3, 4], [5, 6, 7], [8, 9]];

8.函数类型(function)

函数类型实际上,是指定函数参数和返回值的类型。(必须有返回值)

// 方式一
function add1(num1: number, num2: number): number {
    return num1 + num2;
};
console.log(add1(1, 2)); // 3

// 方式二(箭头函数)
const add2 = (num1: number, num2: number): number => {
    return num1 + num2;
};
console.log(add1(2, 3)); // 5

// 方式三
//(写法一)
const add3: (num1: number, num2: number) => number = (n1, n2) => {
    return n1 + n2;
};
console.log(add3(3, 4)); // 7
//(写法二创建类型别名)
type CustomFun = (num1: number, num2: number) => number;
const add4: CustomFun = (n1, n2) => {
    return n1 + n2;
}
console.log(add4(4, 5)); // 9

【函数void类型】

  如果函数没有返回值,则函数返回值类型可设为:void

// void类型
function foo(): void {
    // 不能有return
    console.log('foo被执行了');
}
foo();

【函数可选参数】

  ? :表示可选参数,在可选参数的参数名称后面添加 ?

(可选参数只能出现在参数列表的最后,也就是说可选参数后面不能再出现必选参数)

// 可选参数
function add5(num: number, num1?: number): number {
    if (num1) {
        return num + num1
    } else {
        return num
    }
}
console.log(add5(5)); // 5
console.log(add5(5, 6)); // 11

【函数剩余参数】

  ...变量名:表示剩余参数

// 剩余参数
function getInfo(str1: string, ...str2: string[]): void {
    console.log(str1); // a
    console.log(str2); // ['b', 'c', 'd']
}
getInfo('a', 'b', 'c', 'd');

9.对象类型(object)

对象结构使用 {} 来描述:{属性名: 类型的形式;方法名(): 返回值类型的形式}

如果方法有参数,像定义函数类型一样指定参数类型即可:getName(name: string): void

一行代码中指定多个属性类型时,使用 ;(分号)来分隔多个属性类型

一行代码只指定一个属性类型时,通过换行来分隔多个属性类型(可以去掉 ;

对象结构中定义的属性和方法约束应均有实现,不能多也不能少

// 一行多个属性
let person1: { name: string; age: number; hobby(): void; } = {
    name: '刘六',
    age: 18,
    hobby() {
        console.log('学习');
    }
}
person1.hobby(); // 学习

// 一行一个属性
let person2: {
    name: string
    age: number
    hobby(): void
} = {
    name: '王五',
    age: 20,
    hobby() {
        console.log('学习');
    }
}
console.log(person2.name); // 王五
console.log(person2.age); // 20

【对象可选属性】

  场景:在使用 axios({ ... }) 时,如果发送 GET 请求,则method 属性可以省略。

function Axios(config: { url: string; method?: string }) {
    console.log(config);
}
Axios({ url: '/api', method: 'POST' }); // {url: '/api', method: 'POST'}
Axios({ url: '/api' }); // {url: '/api'}

TS新增数据类型

新增数据类型:联合类型、自定义类型(类型别名)、void、any、元组、枚举、字面量类型、接口等。

1.联合类型

JS原有数据类型--数组类型--【联合类型

2.自定义类型(类型别名)

JS原有数据类型--数组类型--【自定义类型

3.void类型

JS原有数据类型--函数类型--【void类型

4.any类型

当值为any类型时,可以对该值赋任何类型的值,进行任意操作

变量类型一旦设为any,TypeScript 实际上会关闭这个变量的类型检查,失去TS类型保护的优势,即使可能存在错误,也并不会有代码提示。因此不推荐使用any。

【类型保护】

类型保护会在运行时检查变量以确保 TS 变量在特定的块级作用域内属于特定的类型,类型保护的主要思想是尝试检测属性、方法或原型,以确定如何处理值。

隐式具有 any 类型的情况:1.声明变量不提供类型也不提供默认值  2.函数参数不加类型。

// 赋any类型可以做任何操作
let obj: any = { x: 0 };

// 访问不存在的属性 或者 给属性赋值
console.log(obj.aaa); // undefined
obj.aaa = 10; // 赋值

// 对obj赋任何类型的值
obj = "aaa";
console.log(obj); // aaa

// 当作函数调用
obj(); // obj is not a function

// 赋值给其他类型的变量
let n: number = obj;
console.log(n); // {x: 0, aaa: 10}

// 隐式any类型
let a;
a = 'abc';
console.log(a);
a = 123;
console.log(a);

【污染】

类型除了关闭类型检查,还有一个很大的问题,就是它会“污染”其他变量。它可以赋值给其他任何类型的变量(因为没有类型检查),导致其他变量出错。这种错误要在运行时才能报错。

let x:any = 'hello';
let y:number;

y = x; // 不报错

y * 123 // 不报错
y.toFixed() // 不报错

5.unknown类型

为了解决any类型“污染”其他变量的问题,TypeScript 3.0 引入了unknown类型。一般来说,凡是需要设为any类型的地方,通常都应该优先考虑设为unknown类型。

与any类型相似,

所有类型的值都可以分配给unknown类型。

let a: unknown;

a = "a"; // 正确
a = true; // 正确
a = { x: 1, y: 2 }; // 正确

与any类型不同,

unknown类型变量不能直接赋值给其他类型的变量(除了any类型和unknown类型)。赋值给any和unknown以外类型的变量都会报错,这就避免了污染问题。

let b:unknown = 123;

let b1:boolean = v; // 报错
let b2:number = v; // 报错

unknown类型变量不能直接调用其方法和属性

let c1:unknown = { foo: 123 };
console.log(c1.foo); // 报错

let c2:unknown = 'hello';
c2.trim(); // 报错

unknown类型变量能够进行的运算是有限的,只能进行比较运算(运算符==、===、!=、!==、||、&&、?)、取反运算( ! )、typeof运算符和instanceof运算符这几种,其他运算都会报错。需要经过“类型缩小”,unknown类型变量才可以使用。所谓“类型缩小”,就是缩小unknown变量的类型范围,确保不会出错。

let d: unknown = 1;

d += 1; // 报错

if (typeof d === 'number') {
    d += 1; // 正确
}

let s: unknown = 'hello';
console.log(s.length); // 报错


if (typeof s === 'string') {
    console.log(s.length); // 正确
}

6.never类型

为了保持与集合论的对应关系,以及类型运算的完整性,TypeScript 还引入了“空类型”的概念,即该类型为空,不包含任何值。类型为never,则不能赋给它任何值,否则都会报错。

let e: never;
e = false; // 报错

场景:当一个变量可能有多种类型(即联合类型),通常需要使用分支处理每一种类型。这时,处理所有可能的类型之后,剩余的情况就属于never类型。

function fn(x:string|number) {
  if (typeof x === 'string') {
    // ...
  } else if (typeof x === 'number') {
    // ...
  } else {
    x; // never 类型
  }
}

7.元组类型

解决问题:(arr:number[])如此设置数组的类型注解,此数组中可以出现任意多个数字。

元组类型是另一种类型的数组,元组类型可以确切地标记出有多少个元素,以及每个元素的类型

let arr: [number, string, boolean] = [12, 'abc', true];
console.log(arr); // [12, 'abc', true]

场景:使用经纬度坐标来标记位置信息。

let position: [number, number] = [39.3425, 117.2378];
console.log(position); // [39.3425, 117.2378]

8.字面量类型

任意的 JS 字面量(字符串、数字等)都可以作为类型使用。

优点:字面量类型更加精确、严谨。

const str1: 'Hello' = 'Hello'; // str1的值只能是字符串Hello
let age: 18 = 18; // age的值只能是数字18

场景:用来表示一组明确的可选值列表(字面量类型往往配合联合类型一起使用)

function changeDirection(direction: 'up' | 'down' | 'left' | 'right') { };
changeDirection('left'); // 参数direction的值只能是up/down/left/right中的任意一个。

9.枚举类型(enum)

枚举类型enum定义一组明确的可选值。不过一般使用(字面量类型+联合类型组合)的方式定义可选值列表。

其他类型仅仅被当做类型,而枚举不仅用作类型,还提供值(枚举成员都是有值的)。

注意:1.约定枚举名称、枚举中的值以大写字母开头。2.枚举中的多个值之间通过 , (逗号)分隔。3.定义好枚举后,直接使用枚举名称作为类型注解。4.直接通过点 . (点)访问枚举成员。

// demo.ts
enum Sex{
    Man,
    Woman,
    Secrecy
};
function changeSex(sex: Sex) {};
changeSex(Sex.Man); // 将枚举成员做实参使用

 其他的类型会在编译为 JS 代码时自动移除,但是,枚举类型会被编译为 JS 代码

// demo.js
var Sex;
(function (Sex) {
    Sex["Man"] = "MAN";
    Sex["Woman"] = "WOMAN";
    Sex["Secrecy"] = "SECRECY";
})(Sex || (Sex = {})); // 若有值即为Sex,没有值设为{}

 解释:先声明一个变量Sex,然后使用自执行函数将Sex设为对象并向Sex对象中添加属性。

【数值枚举】

  枚举成员若未设置值,默认为:从0开始自增的数值。

enum Elem {
    A,
    B,
    C
}
console.log(Elem.A, Elem.B, Elem.C); // 0 1 2

可以从第任意个成员设置初始值,其后未设置值的成员的值会默认自增。

enum Elem {
    A,
    B = 10,
    C,
    D = 20,
    E
}
console.log(Elem.A, Elem.B, Elem.C, Elem.D, Elem.E); // 0 10 11 20 21

【字符串枚举】

字符串枚举没有自增行为,因此,字符串枚举的每个成员均必须有初始值

enum Sex {
    Man='MAN',
    Woman='WOMAN',
    Secrecy='SECRECY'
};
console.log(Sex.Man, Sex.Woman, Sex.Secrecy); // MAN WOMAN SECRECY

typeof 操作符

众所周知,JS 中提供了 typeof 操作符,用来获取数据的类型。TS 也提供了 typeof 操作符:可以在类型上下文中引用变量或属性的类型(类型查询)作为类型注解,以此来简化类型书写。

注意:typeof 只能用来查询变量或属性的类型。

let p: { x: number; y: number } = { x: 1, y: 2 };

function changeP(point: typeof p) { 
// 等价于 function changeP(point: { x: number; y: number }) {}
    console.log(point); // {x: 50, y: 100}
}; 
changeP({ x: 50, y: 100 })

/* ================================================== */

function add(num1: number, num2: number): number {
    return num1 + num2
}

let reAdd: typeof add = (n1, n2) => {
// 等价于 let reAdd: (num1: number, num2: number) => number
    return n1 + n2
}
reAdd("a",1); // 错误
console.log(reAdd(2, 3)); // 5

 

TypeScript 教程——阮一峰·著

TypeScript 中文网

TypeScript 官网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值