目录
- TypeScript
- 基础类型
- boolean
- number
- string
- any
- unknow
- void
- never
- 数组类型
- type
- 函数
- 函数类型
- 函数表达式
- 可选参数
- 默认参数
- 函数赋值
- interface
- 基本用法
- 可选概念
- 只读属性
- interface 描述函数类型
- 可索引的类型
- 类
- 基本写法
- 继承
- 修饰符
- public
- private
- protected
- 多态
- static
- abstract
- implements
- 泛型
- 基本使用
- 在函数中使用泛型
- 在接口中使用泛型
- 在类中使用泛型
- 泛型约束
- 命名空间
- 断言
- 枚举
- 高级类型
- 交叉类型
- 联合类型
- 类型守卫
TypeScript
基础类型
boolean
let flag1: boolean = true;let flag2: boolean = false;
number
let num1: number = 1;let num2: number = 2;
string
let str1: string = "1";let str2: string = "2";
any
不清楚用什么类型,可以使用
any
类型。这些值可能来自于动态的内容,比如来自用户输入或第三方代码库
let notSure: any = 4;
notSure = "3";
notSure = true
不建议使用 any,不然就丧失了 TS 的意义。注意:只是不建议,但是在某些开发场景上还是可以使用any的。
unknow
unknown
类型代表任何类型,它的定义和any
定义很像,但是它是一个安全类型,使用unknown
做任何事情都是不合法的。/
function divide(param: unknow) {
return param / 2;
}
void
function sum(): void { console.log(`void返回值`);}
never
never
类型表示的是那些永不存在的值的类型。有些情况下值会永不存在,比如,- 如果一个函数执行时抛出了异常,那么这个函数永远不存在返回值,因为抛出异常会直接中断程序运行。- 函数中执行无限循环的代码,使得程序永远无法运行到函数返回值那一步。
function fn(msg: string): never { throw new Error(msg)}
数组类型
// 数组类型
let arr: number[] = [1, 2, 3, 4, 5];
let arr1: string[] = ["1", "2", "3", "4"];
let arr2: boolean[] = [true, false, true, false]
type
// string
type custom = string
let str1: custom = "1";
let str2: custom = "2";
// number
type num = number;
let num1: num = 1;
let num2: num = 2;
函数
函数类型
function add(num1: number, num2: number): number {
return num1 + num2;
}
函数表达式
// 函数表达式
let add2 = (num1: number, num2: number): number => num1 + num2
可选参数
// 可选参数
let add3 = (num1: number, num2: number, num3?: number): number => { return num1 + num2}console.log(add3(1, 2)); 3console.log(add3(1, 2, 3)); 3
默认参数
// 默认参数
function sum(num1: number, num2: number = 100): number { return num1 + num2}
函数赋值
let add2 = (x: number, y: number): number => { return x + y} const add3:(x: number, y: number) => number = add2
interface
interface
(接口) 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述。### 基本概念。
基本用法
// interface
interface person {
name: string
age: number,
address: string
}
let me: person = {
name: 'eason',
age: 21,
address: '广东云浮'
}
console.log(me)
// { name: 'eason', age: 21, address: '广东云浮' }
可选概念
在使用
interface
进行变量的类型定义时,可以使用在变量名后添加?,代表该变量是可选变量,即使对象中不存在该变量也不会报错。
interface person1 {
name: string,
age: number,
address?:string
}
let me1: person1 = {
name: 'eason',
age: 21
}
// { name: 'eason', age: 21 }
只读属性
interface person2 {
readonly id:number,
name:string,
age:string,
address:string
}
let m2: person2 = {
id: 1,
name: 'eason',
age: 21,
address: '广东'
}
console.log(me2.id);
me2.id = 2 // 无法为“id”赋值,因为它是只读属性。
console.log(me.2d);
interface 描述函数类型
interface ISum {
(x:number,y:number):number
}
const add:ISum = (num1, num2) => {
return num1 + num2
}
可索引的类型
let arr: likeArray = ['hello', 'lin'];
console.log(arr[1]);
类
基本写法
class Person {
name: string
constructor(name: string) {
this.name = name;
}
speak() {
console.log(`${this.name} is speaking`);
}
}
const p1 = new Person('eason');
console.log(p1.name);
p1.speak();
继承
// 继承
class employee extends Person {
address: string
constructor(name: string, address: string) {
super(name)
this.address = address
}
speak() {
console.log(`我叫${this.name},在${this.address}工作`)
}
}
new employee("eason", "广州海珠").speak()
修饰符
在TypeScript里,成员都默认为
public
。
public
class Person {
public name: string
public constructor(name: string) {
this.name = name;
}
public speak() {
onsole.log(`${this.name} is speaking`);
}
}
private
当成员被标记成
private
时,它就不能在声明它的类的外部访问。
class employee extends Person {
private address: string
constructor(name: string, address: string) {
super(name);
this.address = address;
}
speak() {
console.log(`我叫${this.name},在${this.address}工作`)
}
}
new employee("eason", "广州海珠").address
// 属性“address”为私有属性,只能在类“employee”中访问。
protected
protected
修饰符与private
修饰符的行为很相似,但有一点不同,protected
成员在派生类中仍然可以访问。继承它的子类可以访问,实例不能访问。
// 基础写法
class Person {
protected name: string
public constructor(name: string) {
this.name = name;
}
public speak() {
console.log(`${this.name} is speaking`);
}
}
// 继承
class employee extends Person {
public address: string
constructor(name: string, address: string) {
super(name)
this.address = address
}
speak() {
console.log(`我叫${this.name},在${this.address}工作`)
}
}
new employee("eason", "广州海珠").name
// 错误
多态
子类对父类的方法进行了重写,子类和父类调同一个方法时会不一样。
class employee extends Person {
public address: string
constructor(name: string, address: string) {
super(name)
this.address = address
}
speak() {
console.log(`我叫${this.name},在${this.address}工作`)
}
}
static
static
是静态属性,可以理解为是类上的一些常量,实例不能访问。
class circle {
static pi: number = 3.14
public radius: number
public constructor(radius: number) {
this.radius = radius
}
public calcLength() {
return circle.pi * this.radius;
}
}
console.log(new circle(10).calcLength());
abstract
抽象类:是指只能被继承,但不能被实例化的类>> 特点:>> - 抽象类不允许被实例化> - 抽象类中的抽象方法必须被子类实现
abstract class Animal {
constructor(name: string) {
this.name = name
}
public name: string
public abstract sayHi(): void
}
class Dog extends Animal {
constructor(name: string) {
super(name)
}
// 没有该行代码会报错
public sayHi(): void {
console.log("hi");
}
}
implements
implements 是实现的意思,class 实现 interface。
interface MusicInterface {
playMusic(): void
}
class Cellphone implements MusicInterface {
playMusic() {}
}
泛型
基本使用
function print<T>(arg: T): T {
return arg;
}
在函数中使用泛型
function print<T>(arg: T): T {
console.log(Object.prototype.toString.call(arg));
return arg;
}
在接口中使用泛型
interface Search {
<T, Y>(name: T, age: Y): T
}
let fn: Search = function <T, Y>(name: T, id: Y): T {
console.log(name, id);
return name
}
fn('eason', 12)
在类中使用泛型
class person<T> {
public name: T
constructor(name: T) {
this.name = name
}
action<T>(say: T) {
console.log(say);
}
}
let me = new person("eason")me.action("eason")
泛型约束
在TypeScript中,可以使用泛型约束来限制泛型类型的范围。
在TypeScript中,可以使用
extend
关键字来增加泛型约束。例如:interface Lengthwise { length: number; } function logginIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); return arg; }
上面的示例中,
T extend Lengthwise
表示泛型参数T必须满足Lengthwise
接口要求,即具有length
属性。在泛型约束中,还可以使用多哥约束,使用
&
连接,例如:function getPropoty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; }
命名空间
在日常开发中,当我们想要在interface中继续添加export的ts规则时,我们可以使用namepace(命名空间)来修饰interface,同时在interface中定义需要export的规则即可。
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
const lettersRegexp = /^[A-Za-z]+$/;
const numberRegexp = /^[0-9]+$/;
export class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
}
断言
- 类型断言
TypeScript 的类型断言是一种向编译器、编辑器和代码阅读器传达某些变量类型的方法。类型断言使得程序员可以在编写代码时
收到指定某个变量的类型,这对于一些特定场景下的变量类型转换或者手动指定类型非常有用。
在TypeScript中,有两种类型断言的语法,分别是“尖括号”语法和“as”语法。
尖括号语法
尖括号语法是在待转换变量前面使用尖括号来指定变量的类型,这里的尖括号并不是泛型类型参数的语法,其作用类似于强制类型转换,但并不是真正的强制类型转换。
尖括号语法的格式如下:
let variableName = <type> value
例如:
let myVariable: any = 'hello world'; let myString: string = <string> myVariable;
在上面的代码中,我们定义了一个
myVariable
变量,它的类型为any
。我们可以使用尖括号语法,将myVariable
变量的类型强制转换成string
类型,并将结果赋值给myString
变量。as语法
不同于尖括号语法,as语法实在待转换变量后面使用as标记来指定变量的类型,这是TypeScript2.0引入的新语法。
as语法的格式如下:
let variableName = value as type;
例如:
let myVariable: any = 'hello wolrd'; let myString: string = myVariable as string;
在这个例子中,我们将
myVariable
变量的类型强制转换成string
类型,并将结果赋值给myString
变量。需要注意的是,在这里将类型传给 as 标记使用的是 type,而不是类型名,这是因为 type 表示被转换的类型,而不是类型名。需要注意的是:,TypeScript 数字类型不能直接转换成字符串类型,需要使用 toString() 方法进行转换。也就是说,在使用 as 语法或尖括号语法时,需要确保类型转换是合法的,否则可能会导致类型错误或运行时错误。
- 非空断言
在TypeScript2.0版本中,引入了非空断言语法,使用
!
符号来表示一个表达式的值不为null
或者undefined
,并告诉TypeScript编译器不必生成类检查。在TypeScript中一个变量可以被定义为可以为null
或undefined
,或者根本没有被初始化,这时候为了避免变量为空时出现类型报错,可以使用非空断言操作符。这种操作符将告诉编译器该变量不为空,从而避免变量为空的类型报错。let myString: string | undefined = 'hello world'; // 1. 使用非空断言操作符 let length: number = myString!.length; // 2. 通过 if 语句处理 null 或 undefined 变量 if (myString) { let length: number = myString.length; }
枚举
在TypeScrip中,枚举(Enum)是一种数据类型,用于定义一组命名的常量值,枚举类型可以提高代码的可读性和可维护性,因为用枚举常量替换魔法数字或字符串可以使代码更加具有可读性和清晰度。
TypeScript 中的枚举与其他语言中的枚举类似,在 TypeScript 中定义枚举的语法如下:
enum EnumName { value1, value2, value3, }
其中,
value1
、value2
、value3
是枚举成员,可以是数字或字符串。如果枚举成员没有指定数值,则默认从0开始自增。枚举成员可以手动指定数值。enum Good { A = 1, B, C = B * 2, }
在上面的代码中,
A
的值为 1,B
的值为 2,C
的值为 4。
高级类型
交叉类型
在TypeScript中,交叉类型(Intersection Types)是指将多个类型合并为一个类型,新类型包含了所有被合并类型的特征,通过交叉类型,可以将多个类型进行组合,以创建更复杂的类型。
使用交叉类型时,可以使用
&
操作符将多个类型进行合并。type admin = { name: stirng, permission: string[]; } type Developer = { name:string, tools: string[] } type DevAdmin = Developer & Admin const eason: DevAdmin = { name: 'eason, permission: ['read', 'write', 'execute'], tooles:['VS Code', 'GitHub']; }
使用
&
运算符合并的类型,新类型将包含合并的类型的所有成员属性和方法。如果两个合并类型有相同的属性或方法,则新类型的属性和方法将包含两个原始类型的属性或方法。如果两个类型有相同属性的不同类型,则交叉类型的属性将是两个属性的并集。交叉类型常用于混合多个对象类型或多个类型。它可以与其他 TypeScript 类型一起使用,例如泛型类型、联合类型等,以定义复杂的类型。
联合类型
联合类型(Union Types)是一种 TypeScript 中的高级类型,它允许我们将多个类型组合在一起,形成一个新的类型,这个新的类型可以是它所组合的类型集合中的任意一个类型。
联合类型使用竖线(|)将多个类型合并在一起,并且可以在函数参数和返回值、变量、接口等各种类型声明中使用。
例如:function printID(id: string | number) { console.log(id); } printID('abc123'); // 输出:abc123 printID(123); // 输出:123
需要注意的是,联合类型并不意味着类型可变或者任意类型,而是对一个实例可以有多种形态进行类型限制,使用时需要谨慎。
类型守卫
类型守卫是指编程语言在某个作用域中,编译器可以通过某些方式确定一个变量的类型,从而可以在后续使用中,智能地应用相关类型的特性。在 JavaScript 和 TypeScript 中,可以使用多种方式来实现类型守卫,其中最常见的是条件判断和类型断言。
条件判断
通过条件判断可以在相应的分支中确定变量的类型。例如:function print(strOrNum: string | number) { if (typeof strOrNum === 'string') { console.log(`The string is: ${strOrNum}`); } else { console.log(`The number is: ${strOrNum}`); } }
在这个例子中,通过判断 strOrNum 变量的类型,可以在不同的分支中打印不同的字符串。这样,在使用变量时就可以智能地应用不同的类型特性。
类型断言
类型断言是指通过手动指定一个变量的类型来告诉编译器,变量的类型是确定的。例如:function print(strOrNum: string | number) { const length = (strOrNum as string).length; console.log(`The length is: ${length}`); }
通过类型断言 strOrNum as string,可以将变量 strOrNum 的类型确定为 string,从而可以使用 string 类型的方法 length。