文章目录
-
-
- [一.TS 基础概念](#一.TS 基础概念)
-
- 1.什么是TS
- 2.TS基础类型与写法
- [* boolean string number array null undefined](#* boolean string number array null undefined)
- [* tuple - 元组](#* tuple - 元组)
- [* enum - 枚举](#* enum - 枚举)
- [* any unknown void](#* any unknown void)
- [* object | Object | {} - 对象](#* object | Object | {} - 对象)
- [二. 接口 - interface](#二. 接口 - interface)
- 三.交叉类型
- [四.断言 - 类型声明,转换](#四.断言 - 类型声明,转换)
- [五.类型守卫 -Type Guards](#五.类型守卫 -Type Guards)
- 六.TS进阶
-
- [1.泛型(Generics) - 重用](#1.泛型(Generics) - 重用)
- [2.装饰器 - decorator](#2.装饰器 - decorator)
-
一.TS 基础概念
1.什么是TS
-
对比原理
-
ts是 js 的一个超集,在原有基础上添加了
-
可选静态类型
-
基于类的面向对象编程
- 编写项目 - 更利于架构维护
- 自主检测 - 编译期间检测
- 类型检测 - 支持了动态和静态类型检测;ts不是强类型语言=》本质上还是存在类型转换
- 运行流程 - 依赖编译
- 复杂特性 - 模块化,泛型,接口
2.TS基础类型与写法
* boolean string number array null undefined
typescript
// es
let isEnable = true;
let class = "ts";
let classNum = 2;
let classArr = ["basic","execute"];
// ts
let isEnable:boolean = true;
let class:string = "ts";
let classNum:number = 2;
// 数组的两种写法
let classArr:string[]= ["basic","execute"];
let classArr:Array<string> = ["basic","execute"];
* tuple - 元组
数组的搭配比较多样,用来声明数组中有多种类型时使用
typescript
let tupleType:[string,boolean]
tupleType =["ts",true]
* enum - 枚举
typescript
// 数字枚举- 默认从零开始,依次递增
enum Score {
BAD,
NG,
GOOD,
PERFECT
}
let score:Score = Score.BAD;
// 字符串类型
enum Score {
BAD="BAD",
NG="NG",
GOOD="GOOD",
PERFECT="PERFECT"
}
// 反响映射
enum Score {
BAD,
NG,
GOOD,
PERFECT
}
let scoreName = Score[0]; // "BAD",因为默认依次递增
let scoreValue = Score["BAD"];// 0
// 异构 (数字和字符串都有)
// 字符串设置什么就是什么
// 数字类型依据上一个加一
enum Score {
A, //0
B, //1
C='C',
D="D",
E=6,
F // 7
}
* any unknown void
typescript
// 输入
//any - 绕过所有检查 => 类型检测和编译筛查全部失效
let anyValue:any =123;
anyValue ="anyValue";
// unknown - 绕过赋值检查=> 禁止更改传递
// 传递
let unkonwnValue:unknown;
unknownValue="unknownValue";
let value1:unknown =unknownValue;//ok
let value2:any=unknownValue;//ok
let value3:boolean = unknownValue;/nok
// 返回
// void - 声明函数返回值 不返回任何值
function voidFunction():void{
console.lg("no return")
}
// nerver - 永不返回
function error(msg:string):never{
throw new Error(msg)
}
function longlongloop():never{
while(true)
}
* object | Object | {} - 对象
typescript
// object - 非原始类型
interface ObjectConstrutor {
create(o:object | null):any;
}
const proto = {};
Object.create(proto);//ok
// Object - 原型属性
// Object.prototype 上的属性
interface Object {
constructor:Function;
toString():string;
valueOf():Object
}
// {} - 空对象 - 没有成员的对象
const a = {} as A; // 通过断言来设置
a.class = "es";
a.name=30; // {} 表示空对象,赋值会抛出异常
二. 接口 - interface
在TypeScript中,接口是一种定义对象形状的方式,它描述了对象应该有哪些属性和方法,但并不直接提供这些属性和方法的实现。接口主要用于确保类或其他结构(如对象字面量)符合特定的契约
- 定义属性:接口可以定义对象的属性类型,但不包括属性值。
- 定义方法:接口可以定义对象的方法,但不包括方法的实现
- 只读属性:使用 readonly 关键字可以定义只读属性,即这些属性只能做对象被创建时被赋值,之后不能被修改
- 继承接口:一个接口可以继承另一个或者多个接口,从而继承它们的属性和方法
javascript
interface Class {
name:string;
time:number
}
let course:Class = {
name:"ts",
time:2
}
//只读
interface Class {
readonly name:string;
time:number
}
// 任意
interface Class {
name:string;
time:number
[propName:string]:any
}
// 面试题:ts 和 js的引用的不同
let arr:number[] = [1,2,3,4];
let ro:ReadonlyArray<number> = arr;
ro[0] = 12; //Error - 只读状态不可赋值
ro.push(5); //Error - 增加
ro.length = 100; //Error - 长度改写
arr = ro;//Error - 覆盖
//定义方法
interface Greeter {
greet(message: string): void;
}
class PersonGreeter implements Greeter {
greet(message: string) {
console.log(`Hello, ${message}`);
}
}
//继承
interface Named {
name:string;
}
interface Person extends Named{
age:number
}
const person:Person = {
name:"张三",
age:18
}
三.交叉类型
在TypeScript中,交叉类型是一种组合多个类型到一个单一类型的方式。通过交叉类型,你可以创建一个新的类型,这个类型具有所有被组合类型的特性。当一个对象具有多个类型的属性时通过&符号来定义的
- 交叉类型和运算符里面的 与( && ) 是一样的,既要 ... 又要 ... 还要
- 可以把两个对象合并到一个对象
typescript
// 合并
interface A {x:D}
interface B {x:E}
interface C {x:F}
interface D {d:boolean}
interface E {e:string}
interface F {f:number}
type ABC = A & B & C;
let abc:ABC ={
x:{
d:false,
e:"class",
f:5
}
}
// 合并冲突
interface A {
c:string;
d:string
}
interface B {
c:number;
d:string
}
type AB = A & B;
// 合并关系是并且 => c:never
四.断言 - 类型声明,转换
在TypeScript中,断言是一种告诉编译器我们对某个表达式类型的明确预期的方式。通过使用断言,我们可以为编译器提供额外的信息,以确保在编译时能够正确地处理类型。断言不仅用于声明变量的类型,还可以用于在类型之间进行显式转换,从而确保代码的类型安全性。
typescript
// 尖括号
let anyValue:any = 'hi ts';
// 当anyValue是 string 时去取length
let anyLength:number = (<string>anyValue).length; //阶段性声明;
// as 声明
let anyLength:number = (anyValue as string).length; //阶段性声明;
// 非空判断 - 非空断言操作符 !
// 非空断言操作符,用于告知编译器我确定这个值是非空的,不需要再进行类型检查
type ClassTime = () => number;
const start = (classTime:ClassTime | undefined)=>{
let num = classTime!(); //确认一定不会为空
}
五.类型守卫 -Type Guards
在TypeScript中,类型守卫是一种特殊的表达式,它允许你执行运行时检查以缩小一个值的类型范围。类型守卫可以用于确保一个值是某种特定的类型,或者在多种类型之间进行区分。
typeof | instanceof 类型守卫
在TypeScript中,typeof 和 instanceof 运算符被特殊对待,并被认为是类型守卫。当它们用于类型检查时,TypeScript会缩小变量的类型范围。
typescript
interface Teacher {
name:string;
courses:string[];
}
interface Student{
name:string;
startTime:Date;
}
type Class = Teacher | Student
function startCourse(cls:Class){
if('courses' in cls){
// teacher
}
if("startTime" in cls){
// student
}
}
function startCourse(cls:Class){
if(cls intanceof Teacher){
// teacher
}
if(cls intanceof Student){
// student
}
}
function startCourse(name:string,score:string | number){
if(typeof score === "number"){
// teacher
}
if(typeof score === "string"){
// student
}
}
六.TS进阶
1.泛型(Generics) - 重用
在 TypeScript 中,泛型是一种允许你为组件(如类、接口和函数)创建可复用的类型的方式,而无需在每次使用组件时都明确指定类型。泛型提供了一种创建可重用组件的方式,这些组件可以工作于多种数据类型。
- 泛型函数:泛型函数是指在调用指定类型参数的函数。在函数后面使用(其中 T 是类型变量)
- 泛型类:泛型类是在类定义中使用类型变量的类
- 泛型接口:中接口定义中引入类型变量
- 泛型约束:定义泛型时,可以对泛型参数添加一些约束,以确保它符合某些结构。可以通过中类型参数上设置extends 约束来实现
- 类型推断与默认类型:typeScript的类型推断机制可以自动推断泛型类型参数;泛型类型可以设置默认类型
typescript
//泛型函数
function startClass<T,U>(name:T,score:U):T{
return name + score
}
console.log(startClass(<string,number>('yy',5)))
function startClass<T,U>(name:T,score:U):string{
return `${name}${score}`
}
function startClass<T,U>(name:T,score:U):T{
return (name + String(score)) as any as T;
}
// 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identityFn<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identityFn;
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在我们可以访问.length属性了
return arg;
}
// 使用泛型约束
loggingIdentity({length: 10, value: 3});
2.装饰器 - decorator
在 TypeScript 中,装饰器是一种特殊类型的声明,它可以被附加到类声明、方法、访问符、属性或参数上。装饰器使用 @expression 的形式,其中 expression 必须在运行时求值为一个函数,它将在编译时调用,
装饰器可以使用在许多不同的上下文中,但它们的主要用途是修改类的行为,为类添加元数据,或者为类、方法、属性等提供额外的功能。
typescript
function Roo(target:Function):void{
// 拿到的类
target.prototype.startClass = function():void{
// 逻辑
}
}
// 类装饰器
@@Roo
class Course {
constructor(){
// 业务逻辑
}
}
// 属性装饰器
function nameWrapper(target:any,key:string){
// 逻辑处理
Object.defineProerty(target,key){
// 数据劫持
}
}
class Course {
constructor(){
// 业务逻辑
}
@nameWrapper
public name:string
}