目录
一、TypeScript的基本概念与编译
1.1.基本概念
1.2.TypeScript优缺点
二、TS的基础类型
布尔类型
数字类型
字符串类型
数组类型
元组类型
枚举类型
1.数字枚举
2.字符串枚举
3.复合枚举
枚举的高级用法
any类型
unknown类型
三、TypeScript的进阶概念
联合类型
类型别名
类型推断
类型断言
对象(Object)
接口(interface)
接口的基本用法
可选属性
只读属性
函数类型
索引签名
接口的继承
函数
一、TypeScript的基本概念与编译
1.1.基本概念
定义:TypeScript是JavaScript的超集,它继承了JavaScript的全部语法,并添加了一些新的特性,如静态类型检查、类和接口等。这使得TypeScript更适合用于开发大型、复杂的企业级项目。
目的:TypeScript的目的并不是创造一种全新语言,而是增强JavaScript的功能,提高代码的可读性和可维护性。
编译:TypeScript代码需要编译成JavaScript代码才能在浏览器中运行。编译过程会删除类型声明和类型相关的代码,只保留能运行的JavaScript代码。
1.2.TypeScript优缺点
typescript 指的是js的升级版本 其实就是给js添加类型
优点:增强了代码的可维护性,特别是大型项目;友好的快速的能在编辑器中提示错误,在编译阶段就能发现大部分错误;支持最新的JavaScript 的新特性
缺点:需要一定的学习成本和一些插件库不是很兼容;增加了前期的开发成本(开发速度)
tsc 文件名 就是编译ts 文件
tsc --init 生成ts的配置文件
二、TS的基础类型
布尔类型
// ts 声明一个布尔类型
let c:boolean;
//:boolean 类型注解 作用:给变量添加类型约束,约束什么类型 就只能赋值什么类型
c = false
数字类型
// ts 声明数字类型
let a:number;
//声明变量 :number类型注解
a = 200;//赋值
console.log(a);
字符串类型
// ts 声明一个字符串类型
let b:string;
b = "张三";
数组类型
// let arr=[];
// 写法1
// let arr:any[]=[];
// 写法2
// let arr:Array<any> = [];// 定义数组的一种方式
let a: number[] = [];//只能是数字类型
let b: Array<number> = [];//只能是数字类型
let c: (number | string)[] = [];//既可以是数字类型也可以是字符串
let d: (boolean | string)[] = [];//既可以是布尔类型也可以是字符串interface PeopleType {name: string,age: number,sex: string
}
// [{ name: "张三", age: 22, sex: "男" }, { hame: "张三", age: 22, sex: "男" }]//数组对于对象的类型注解
let peoplelList:PeopleType[]= [{name:"张三",age:22,sex:"男"},{name:"张三"
,age:22,sex:"男"}]export { };
元组类型
// 元组 tuple 表示一个已知数量和类型的数组(特殊数组)
let tup:[number,string,boolean,number] = [1,"222",false,1111];
枚举类型
枚举 enum 用于定义数值的集合,通常用于定义一组有规则的数据 比如周一到周天
枚举 根据存储值不同分为三种:数字枚举、字符串枚举、符合枚举。
1.数字枚举
枚举成员会被赋予一个递增的数字值,默认从0开始
enum Day {Sunday, // 0Monday, // 1Tuesday, // 2Wednesday, // 3Thursday, // 4Friday, // 5Saturday // 6
}console.log(Day.Sunday); // 输出: 0
console.log(Day.Monday); // 输出: 1
console.log(Day[2]); // 输出: "Tuesday" (反向映射)
也可以手动赋值,未手动赋值的成员会基于前一个成员的值递增
enum Direction {Up = 1,Down, // 2Left, // 3Right // 4
}
2.字符串枚举
enum DirectionString {Up = "UP",Down = "DOWN",Left = "LEFT",Right = "RIGHT"
}console.log(DirectionString.Up); // 输出: "UP"
console.log(DirectionString["DOWN"]); // 输出: "DOWN" (反向映射)
3.复合枚举
enum MixedEnum {No = 0,Yes = "YES",Maybe = 100,Absolutely = "ABSOLUTELY"
}console.log(MixedEnum.No); // 输出: 0
console.log(MixedEnum.Yes); // 输出: "YES"
console.log(MixedEnum[100]); // 输出: "Maybe" (反向映射,仅限于数字到名称)
// console.log(MixedEnum["ABSOLUTELY"]); // 错误:字符串到数字的反向映射不被支持
枚举的高级用法
常量枚举:使用 const enum
可以生成更高效的代码,因为它不会在编译后的 JavaScript 中生成实际的对象。
const enum DirectionConst {Up,Down,Left,Right
}let dir: DirectionConst = DirectionConst.Up;
// 编译后的代码不会包含 DirectionConst 对象
枚举成员的类型:枚举成员本身具有类型,并且 TypeScript 会根据上下文自动推断类型
enum ShapeKind {Circle,Square
}function area(shape: ShapeKind) {return shape === ShapeKind.Circle ? 100 : 200;
}
any类型
用来定义一个不确定的类型,任何值都可以赋值给any
anyscript 不要滥用any 不然 ts 就没有意义了
let age2:any;
age2 = 100;
// age2 ="222";
// age2 = true;
// age2 = undefined
unknown类型
任意类型,类似于any类型,但禁止更改传递的值,即只能被赋值不能传递。
拓展:
unknown 和any 区别任何值都可以赋值给any ,同时any也可以赋值给任意类型
unknown 任何类型都可以赋值给它 但是它本身只能赋值给unknown或any
void类型:用于标识方法返回值的类型,表示该方法没有返回值。
never类型:表示永不返回的值或永远返回error的值。
三、TypeScript的进阶概念
联合类型
联合类型(不是一种类型:可以复制多种类型 )
let age:number|string|boolean;//既可以赋值数字也可以赋值字符串
age = 20;
age = "30"
age = true
类型别名
给联合类型起名字 达到复用的效果
type ageType = number|string|boolean
// let pic:numberstring boolean
let pic:ageType;//类型别名使用
pic = 100;
pic = true;
let prop:ageType;//复用 联合类型
类型推断
当类型没有给出时,TypeScript编译器会利用类型推断来推断变量的类型。
let test = "200";
// test = 300 错误
类型断言
在一些特殊情况下,我们比ts 更清楚我们的变量是归属于什么类型,所以我们可以手动设置类型
let a:any = "张三";
let b1 = (a as string).length;// 类型断言
let b2 = (<string>a).length;// 类型断言// 非空断言
let c:string|number|undefined|null = "123"
console.log(c!.length);// 确定赋值断言
// 没有赋值就使用会报错,所以可以通过确定赋值断言来解决
let value!:number;
console.log(value);
export {}
对象(Object)
在 TypeScript 中,对象是通过键值对来定义的,其中键是字符串(或符号),而值可以是任何类型。TypeScript 允许你为对象的属性添加类型注解
let person: { name: string; age: number } = {name: "Alice",age: 30
};
接口(interface)
接口(interface)对行为的抽象,具体行为由类实现。接口可以描述对象的形状,包括属性及其类型。
接口的基本用法
接口通过 interface
关键字来定义。下面是一个简单的接口示例,它定义了一个具有 name
和 age
属性的对象结构:
interface Person {name: string;age: number;
}// 使用接口
let tom: Person = {name: "Tom",age: 30
};
可选属性
有时候,接口中的某些属性可能不是必需的。在这种情况下,你可以使用 ?
标记这些可选属性:
interface Person {name: string;age?: number; // 可选属性
}let tom: Person = {name: "Tom"// age: 30, // 可选属性,可以省略
};
只读属性
如果希望接口中的某个属性在对象被创建后不能被修改,你可以使用 readonly
关键字来标记这个属性
interface Person {readonly name: string;age: number;
}let tom: Person = {name: "Tom",age: 30
};// tom.name = "Jerry"; // 错误:不能给只读属性赋值
tom.age = 31; // 正确:可以修改非只读属性
函数类型
接口不仅可以描述对象的属性,还可以描述对象的函数签名。下面是一个包含函数签名的接口示例:
interface Greeter {greet(name: string): void;
}let greeter: Greeter = {greet(name: string) {console.log("Hello, " + name + "!");}
};greeter.greet("Tom"); // 输出: Hello, Tom!
索引签名
索引签名允许你描述对象上可能存在的属性键和值的类型。这对于描述那些可能具有任意数量属性的对象特别有用
interface StringIndexedArray {[index: string]: number;
}let myArray: StringIndexedArray;
myArray["foo"] = 1; // 正确:属性键是字符串,属性值是数字
myArray["bar"] = 2; // 正确// myArray[3] = "hello"; // 错误:属性键应该是字符串,而不是数字
接口的继承
接口之间可以相互继承,从而可以基于一个接口定义另一个接口,并添加新的属性或函数签名
interface Animal {name: string;
}interface Dog extends Animal {bark(): void;
}let dog: Dog = {name: "Rex",bark() {console.log("Woof! Woof!");}
};
类(class)
类:提供了一种更结构化的方式来定义对象的属性和方法。类可以包含构造函数、属性、方法、访问修饰符(如 public
、private
和 protected
)以及继承等特性
class Animal {name: string;constructor(name: string) {this.name = name;}speak() {console.log(`${this.name} makes a sound.`);}
}
函数
TypeScript 为函数参数和返回值添加了类型注解
function greet(name: string): string {return "Hello, " + name;
}
泛型:允许在定义函数、接口或类时不指定具体类型,而在使用时再指定类型的一种机制
function identity<T>(arg: T): T {return arg;
}let output = identity<string>("myString");
let numOutput = identity<number>(123);
命名空间(namespace):用于组织代码,避免命名冲突。
namespace Validation {export interface StringValidator {isAcceptable(s: string): boolean;}export class LettersOnlyValidator implements StringValidator {isAcceptable(s: string): boolean {return /^[A-Za-z]+$/.test(s);}}
}let validator = new Validation.LettersOnlyValidator();
构造器
在 TypeScript 中,构造器(constructor)是与类(class)紧密相关的一个概念。构造器是一个特殊的方法,用于在创建类的新实例时初始化该实例。当使用
new
关键字调用类时,构造器会被自动调用。
构造器基本用法
class Person {name: string;age: number;// 构造器constructor(name: string, age: number) {this.name = name;this.age = age;}greet() {console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);}
}// 创建 Person 类的新实例
let alice = new Person("Alice", 30);
alice.greet(); // 输出: Hello, my name is Alice and I am 30 years old.
构造器的访问修饰符
构造器可以有访问修饰符,如
public
(默认)、private
或protected
。然而,由于构造器的主要目的是创建类的实例,因此将其设为private
或protected
并不常见,这会导致类不能在类外部被实例化(对于private
)或不能在子类外部被实例化(对于protected
)
class Singleton {// 私有构造器,防止外部实例化private constructor() {// ...}// 静态方法提供类的唯一实例private static instance: Singleton;public static getInstance(): Singleton {if (!Singleton.instance) {Singleton.instance = new Singleton();}return Singleton.instance;}
}// 尝试直接实例化会报错
// let s = new Singleton(); // 错误:构造器是私有的// 正确获取唯一实例
let s1 = Singleton.getInstance();
let s2 = Singleton.getInstance();
// s1 和 s2 实际上是同一个实例
继承中的构造器
当类被继承时,子类的构造器需要调用父类的构造器,以确保父类被正确初始化。这可以通过在子类构造器中调用
super()
来实现。
class Animal {name: string;constructor(name: string) {this.name = name;}speak() {console.log(`${this.name} makes a sound.`);}
}class Dog extends Animal {breed: string;// 子类构造器需要调用父类构造器constructor(name: string, breed: string) {super(name); // 调用父类构造器this.breed = breed;}bark() {console.log("Woof! Woof!");}
}let dog = new Dog("Rex", "German Shepherd");
dog.speak(); // 输出: Rex makes a sound.
dog.bark(); // 输出: Woof! Woof!
"文字耕耘实属不易,诚挚期待您的点赞支持。"