typescript 类型及使用

本文详细介绍了TypeScript中的各种数据类型,包括数字、字符串、数组、元祖、枚举等基本类型,以及任意类型、void、never等特殊类型,并探讨了自定义类型的方法。


在这里插入图片描述

typescript系列教程

typescript 类型及使用
typescript 三种类修饰符
typescript抽象类 abstract
typescript接口 interface
typescript 泛型常见用法
typescript class可以作为类型定义被扩展
三分钟了解interface和type
typescript 模块化,命名空间
typescript 装饰器全集

数字 number (自然数,浮点数,负数)

let number1: number = 111222;
console.log(number1)
number1 = 12.3
console.log(number1)
number1 = -5
console.log(number1)
// 已经定义为number就不能再将其赋值其它类型
number1 = 'dx';

在这里插入图片描述

字符串类型 string

let str:string = "dx";
console.log(str)
//如果str定为字符串,就只能为其赋值字符串,赋值为number或其它类型会报错
str = 1

在这里插入图片描述

数组类型 array

// 空数组
let array1: [] = [];

// number数组 数组的元素必须全为number类型,否则会报错
let numberArray1: number[] = [1, 2, 3, 4, 5];
// numberArray1.push('dx')
numberArray1.push(2.4);

// 还有一种写法
let numberArray2: Array<number> = [1, 2, 3, 4, 5];

//字符串数组 数组的元素必须全为字符串类型,否则会报错
let stringArray: string[] = ['x', 'y'];

//对象数组 数组的元素必须全为对象,每个对象都必须有a属性,值为number
let objArray: {
  a: number;
}[] = [{ a: 1 }];

元祖类型 tuple(用来规定数组中每一个元素的类型)

元祖是一种特殊的数组类型

// tuple元祖类型是数组类型的一种 限制数组的元素个数,
// 并且限制每一个元素的类型
let tupleArray: [string,number,object] = ['dx',3,{}] 

// 当某个元素不确定是否存在时,这个不确定的元素一定要在必须元素的最后面
let tupleArray: [string,number,object?] = ['dx',3]

// 任意多个元祖,解构赋值的形式进行
let tupleArray1: [string,number,...string[]] = ['dx',3,'a','b','c']
// 只对数组元素的第一个和第二个起到限制作用,后面的不限制
let tupleArray2: [string,number,...any[]] = ['dx',3,'a',18,false] 

枚举类型 enum

  1. 字符串枚举
// 枚举类型enum
enum Flag {
  wait = '待支付',
  success = '已支付',
  error = '有内鬼,终止交易',
}

let EnumWait: Flag = Flag.wait;
console.log(EnumWait); //'待支付'

// 也可以直接一点
console.log(Flag.error);

// 不赋值的枚举,会默认赋值为数组的下标
enum Enum1 {
  a,
  b,
  c,
}
let Enum1Value: Enum1 = Enum1.a;

console.log(Enum1Value); // 0
console.log(Enum1.b); // 1

//不全赋值枚举类型
enum Enum2 {
  a = 2,
  b,
  c,
}
let Enum2Value: Enum2 = Enum2.a;
console.log(Enum2Value); // 2
console.log(Enum2.b); // 3

// 会报错的部分枚举, 不能不赋值枚举的类型,除非它上一个没有被赋值或者赋值为number类型
// enum Enum3 {
// a = 'dx',
// b,
// c,
// }

// 不会报错的部分枚举
enum Enum4 {
  a = 1,
  b,
  c,
}

enum Enum5 {
  a = 'dx',
  b = 1,
  c,
}
  1. 数字枚举一种最常见的枚举类型,其成员的值会自动递增,且数字枚举还具备反向映射的特点,在下面代码的打印中,不难发现:可以通过值来获取对应的枚举成员名称 。

使用数字枚举完成walk函数中的逻辑,此时我们发现: 代码更加直观易读,而且类型安全,同时也更易于维护。

enum Direction {
  Up,
  Down,
  Left,
  Right,
}

function walk(n: Direction) {

  if (n === Direction.Up) {

    console.log("向【上】走");

  } else if (n === Direction.Down) {

    console.log("向【下】走");

  } else if (n === Direction.Left) {

    console.log("向【左】走");

  } else if (n === Direction.Right) {

    console.log("向【右】走");

  } else {
    console.log("未知方向");
  }
}
walk(Direction.Up)
walk(Direction.Down)
  1. 常量枚举

官方描述:常量枚举是一种特殊枚举类型,它使用const关键字定义,在编译时会被内联,避免生成一些额外的代码。

何为编译时内联?

所谓“内联”其实就是 TypeScript 在编译时,会将枚举成员引用替换为它们的实际值,而不是生成额外的枚举对象。这可以减少生成的 JavaScript 代码量,并提高运行时性能。

使用普通枚举的 TypeScript 代码如下:

enum Directions {
  Up,
  Down,
  Left,
  Right
}
let x = Directions.Up;

编译后生成的 JavaScript 代码量较大 :

"use strict";

var Directions;

(function (Directions) {

    Directions[Directions["Up"] = 0] = "Up";

    Directions[Directions["Down"] = 1] = "Down";

    Directions[Directions["Left"] = 2] = "Left";

    Directions[Directions["Right"] = 3] = "Right";

})(Directions || (Directions = {}));

let x = Directions.Up;

使用常量枚举的 TypeScript 代码如下:

const enum Directions {
  Up,
  Down,
  Left,
  Right
}
let x = Directions.Up;

编译后生成的 JavaScript 代码量较小:

"use strict";

let x = 0 /* Directions.Up */;

任意类型 any

// 任意类型 any, 不再受到类型的限制,想怎么赋值就怎么赋值
// 当你不知道某个变量的类型时,可以设置为any
let any1:any = 1
any1 = 'dx'
let any2:any = ''
any2 = 2
let any3:any = {}
let any4:any = function() {}
let any5:any = []

// 你也可以把any类型的数据赋值给其它变量都不会有问题
let name: string = 'dengxi'
name = any2

// 你也可以读取或者调用any类型的任意属性和方法
any5.change(); // 很明显js会报错,any5现在是一个数组类型,并没有change方法可以被调用。但es 不会检验出它的错误,因为any类型就相当于放弃了ts的规则校验

未知类型unknown

未知类型,适用于:起初不确定数据的具体类型,要后期才能确定

let a: unknown 
//以下对a的赋值,均符合规范
a = 100
a = false
a = '你好'

感觉unknown和any很像,差别在哪儿呢?unknown类型只能对其任意赋值,却不能任意使用,这点与any不同,相对来说,它比any规范一点儿,安全一点儿。

let a: unknown = 'dengxi'
let b: boolean = false
b = a // ts会报错,不能将unknown类型赋值给boolean类型,但any类型可以赋值给任意类型。
a.change() // ts会报错,unknown类型不确定有change方法存在,所以unknown类型不能任意使用。
 

null 和 undefined

// undefined 类型 当你不知道某一个变量是否有值时,可以在联合类型中使用undefined
let undefined1: number | undefined = 1;
undefined1 = undefined;

let undefined2: number | undefined = undefined;

// undefined的值只能赋值为undefined
// let undefined3: undefined = null 是不对的


// null类型
let null1:null = null
// null只能赋值为null
// let null2:null = undefined

void类型

void类型,没有任何类型,一般用于方法没有返回值。

// a是一个函数,不接受任何参数,并自动返回undefined
let a: () => void = function () {}

function run(): void {
  console.log(run);
}

// undefined 是void可以接受的一种空
function run1(): void {
  console.log(run1);
  return undefined
}

// 如果方法有返回值number
function run1(): number {
return 123
}

// 如果方法接收参数,返回number
let b: (c:string) => number = function (c) {
  return Number(c)
}

返回void的函数 调用者不应该依赖返回值进行操作

function run1(): void {
  console.log(run1);
  return undefined
}
let result = run1()
// ts 不允许将void的值拿来做任何操作,即使你明白result应该是undefined
if(result === undefined) {
// 是不被ts允许的
}

但如果用undefined 替换void就不存在这种问题

function run1(): undefined {
  console.log(run1);
  return undefined // 即使不写,函数也是默认返回undefined
}
let result = run1()
if(result === undefined) {
// 是不被ts允许的
}

never类型

never表示 不能存在任何值,undefined也不行。

几乎不用never限制变量,没有意义。
一般用于函数中可能报错的逻辑,或者循环调用,永不结束的函数。

// never 类型 表示其它类型,常用于抛出异常,因为我们不知道抛出的异常是一个什么类型,never可以被any代替,不常用
let d: never = (() => {
  throw new Error('未知的错误');
})();

function demo(): never {
	throw new Error('程序异常')
}

object 类型

object(小写)的含义是:所有非原始类型,可存储:对象、函数、数组等,由于限制的范围比较宽泛,在实际开发中使用的相对较少。

// 以下代码,是将【非原始类型】赋给a,所以均符合要求
let a:object // a的值可以是任何【非原始类型】,包括:对象、函数、数组等

a = {}

a = {name:'张三'}

a = [1,3,5,7,9]

a = function(){}

a = new String('123') // 这是string的包装对象,所以也可以赋值给object类型

class Person {}

a = new Person()
// 以下代码,是将【原始类型】赋给a,有警告

a = 1        // 警告:不能将类型“number”分配给类型“object”

a = true     // 警告:不能将类型“boolean”分配给类型“object”

a = '你好'   // 警告:不能将类型“string”分配给类型“object” 

a = null     // 警告:不能将类型“null”分配给类型“object”

a = undefined // 警告:不能将类型“undefined”分配给类型“object” 

Object 类型

官方描述:所有可以调用Object方法的类型。

· 简单记忆:除了undefined和null的任何值。

· 由于限制的范围实在太大了!所以实际开发中使用频率极低。

let b:Object //b的值必须是Object的实例对象(除去undefined和null的任何值)



// 以下代码,均无警告,因为给a赋的值,都是Object的实例对象

b = {}
b = {name:'张三'}
b = [1,3,5,7,9]
b = function(){}
b = new String('123')
class Person {}
b = new Person()
b = 1 // 1不是Object的实例对象,但其包装对象是Object的实例
b = true // truue不是Object的实例对象,但其包装对象是Object的实例
b = '你好'	// “你好”不是Object的实例对象,但其包装对象是Object的实例

// 以下代码均有警告
b = null     // 警告:不能将类型“null”分配给类型“Object”
b = undefined // 警告:不能将类型“undefined”分配给类型“Object” 

type类型

// type 自定义类型,类似于定义一个变量,大驼峰式命名(行业规范,不遵守也不会报错),
// type 是为了方便快捷,当多个数据类型一致时,可以用一个变量的形式将这种类型保存下来,直接使用。

type TestType = [string, number, any];

const TestType1: TestType = ['dx', 18, '牛逼'];

const TestType2: TestType = ['yx', 18, 4564];

// type 自定义,你想怎么玩都可以,能满足复杂数据的类型设置,

type TypeTest = {
  a: number;
  b: string;
  c: () => void;
};

const TypeTest1 = {
  a: 18,
  b: 'dx',
  c: () => {
    console.log(a);
  },
};

// 联合 typea 可以是字符串 数字 布尔值
type Typea = string | number | boolean;

const Typea1: Typea = 1;
const Typea2: Typea = 'dx';
const Typea3: Typea = false;

交叉类型(Intersection Types)允许将多个类型合并为一个类型。合并后的类型将拥有所有被合并类型的成员。交叉类型通常用于对象类型。

//面积
type Area = {
  height: number; //高
  width: number; //宽
};
//地址
type Address = {
  num: number; //楼号
  cell: number; //单元号
  room: string; //房间号
};
// 定义类型House,且House是Area和Address组成的交叉类型
type House = Area & Address;
const house: House = {
  height: 180,
  width: 75,
  num: 6,
  cell: 3,
  room: '702'
};

一个特殊情况
先来观察如下两段代码:

代码段1(正常)

在函数定义时,限制函数返回值为void,那么函数的返回值就必须是空。

function demo():void{

  // 返回undefined合法
  return undefined

  // 以下返回均不合法

  return 100
  return false
  return null
  return []
}

demo()

代码段2(特殊)

使用类型声明限制函数返回值为void时,TypeScript并不会严格要求函数返回空。

type LogFunc = () => void

const f1: LogFunc = () => {

  return 100; // 允许返回非空值

};

const f2: LogFunc = () => 200; // 允许返回非空值

const f3: LogFunc = function () {

  return 300; // 允许返回非空值

};

为什么会这样?

是为了确保如下代码成立,我们知道 Array.prototype.push 的返回值是一个数字,而Array.prototype.forEach方法期望其回调的返回类型是void。

const src = [1, 2, 3];

const dst = [0];

src.forEach((el) => dst.push(el));

官方文档的说明:Assignability of Functions

声明对象类型

1. 实际开发中,限制一般对象,通常使用以下形式 

// 限制person1对象必须有name属性,age为可选属性

let person1: { name: string, age?: number }



// 含义同上,也能用分号做分隔

let person2: { name: string; age?: number }



// 含义同上,也能用换行做分隔

let person3: {

  name: string

  age?: number

}



// 如下赋值均可以

person1 = {name:'李四',age:18}

person2 = {name:'张三'}

person3 = {name:'王五'}



// 如下赋值不合法,因为person3的类型限制中,没有对gender属性的说明

person3 = {name:'王五',gender:'男'}
  1. 索引签名: 允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的,常用于:描述类型不确定的属性,(具有动态属性的对象)。
// 限制person对象必须有name属性,可选age属性但值必须是数字,同时可以有任意数量、任意类型的其他属性

let person: {

  name: string

  age?: number

  [key: string]: any // 索引签名,完全可以不用key这个单词,换成其他的也可以

}



// 赋值合法

person = {

  name:'张三',

  age:18,

  gender:'男' 

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可缺不可滥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值