首页 前端知识 TypeScript入门教程

TypeScript入门教程

2024-09-01 00:09:07 前端知识 前端哥 295 740 我要收藏

目录

  • 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);
        }
    }
}

断言

  1. 类型断言

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 语法或尖括号语法时,需要确保类型转换是合法的,否则可能会导致类型错误或运行时错误。

  1. 非空断言

在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,
}

其中,value1value2value3是枚举成员,可以是数字或字符串。如果枚举成员没有指定数值,则默认从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 中,可以使用多种方式来实现类型守卫,其中最常见的是条件判断和类型断言。

  1. 条件判断
    通过条件判断可以在相应的分支中确定变量的类型。例如:

    function print(strOrNum: string | number) {
      if (typeof strOrNum === 'string') {
        console.log(`The string is: ${strOrNum}`);
      } else {
        console.log(`The number is: ${strOrNum}`);
      }
    }
    

在这个例子中,通过判断 strOrNum 变量的类型,可以在不同的分支中打印不同的字符串。这样,在使用变量时就可以智能地应用不同的类型特性。

  1. 类型断言
    类型断言是指通过手动指定一个变量的类型来告诉编译器,变量的类型是确定的。例如:

    function print(strOrNum: string | number) {
      const length = (strOrNum as string).length;
      console.log(`The length is: ${length}`);
    }
    

    通过类型断言 strOrNum as string,可以将变量 strOrNum 的类型确定为 string,从而可以使用 string 类型的方法 length。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/17339.html
标签
评论
发布的文章

安装Nodejs后,npm无法使用

2024-11-30 11:11:38

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!