TypeScript快速上手

基本类型

  • string:字符串
  • number:数字
  • boolean:布尔值
  • array:数组
  • object:对象
  • null 和 undefined:是所有其他类型的子类型,它们可以赋值给其他类型
    • 设置"strictNullChecks": true// 开启严格空类型检查 null 和 undefined只能赋值给自身

其他常用类型

  • 联合类型(|):多种类型任选一个,配合类型保护进行判断
    • 类型保护:当某个变量进行类型判断之后,在判断的语句中,可以使用typeof进行简单类型检查,确定类型
  • 字面量类型:使用一个值进行约束
  • 元祖类型(Tuple):一个固定长度的数组,并且数组中的每一项的类型都是确定的
  • void:用于约束函数的返回值,表示该函数没有任何返回值
  • never:用于约束函数的返回值,表示该函数没永远不可能结束
  • any:任意类型,对该类型的所有值都可以赋值,ts不进行类型检查

类型别名

对已知的类型定义名称

type 类型名 = ...

函数类型声明

函数重载:在函数实现之前,对函数调用的多种情况进行声明

/**
 * 得到a和b拼接的结果
 * @param a 
 * @param b 
 */
function com(a: string, b: string): string
/**
 * 得到a*b的结果
 * @param a 
 * @param b 
 */
function com(a: number, b: number): number
function com(a: number | string, b: number | string): number | string {
  if (typeof a === 'number' && typeof b === 'number') {
    return a * b
  }
  if (typeof a === 'string' && typeof b === 'string') {
    return a + b
  }
  throw new Error("参数类型不匹配");

}
const result = com(1, 2)
console.log(result);

可选参数:可以在某些参数名后加上问号,表示该参数可以不用传递,可选参数必须在参数列表的末尾

function sum(a: number, b: number, c?: number): number {
  // 类型保护
  if (c) {
    return a + b + c
  }
  else {
    return a + b
  }
}
sum(1, 2)
sum(1, 2, 3)

扩展类型

扩展类型:类型别名、枚举、接口、类

  1. 枚举类型
  • 枚举通常用于约束某个变量的取值范围
  • 字面量和联合类型配合使用,也可以达到同样的目标
    let sex: '男' | '女'
    • 存在的问题:
      • 在类型约束位置,会产生重复代码。可以使用类型别名解决该问题。
      • 逻辑含义和真实的值产生了混淆,会导致当修改真实值的时候,产生大量的修改。
      • 字面量类型不会进入到编译结果。
  1. 枚举

    定义一个枚举:

    enum 枚举名{
     枚举字段 =...
    }
    //例子
     enum Sex {
      male = '男',
      female = '女'
     }
     let sex: Sex
     sex = Sex.male
     console.log(sex); // 男
    

    枚举会出现在编译结果中,编译结果中表现为对象

    枚举的规则:

    • 枚举的字段值可以是字符串或者数字
    • 枚举数字的值会自动增加
    • 被数字枚举约束的变量,可以直接赋值为数字
    • 数字枚举的编译结果和字符串的枚举有差异

最佳实践:

  • 尽量不要在一个枚举中既出现字符串字段,又出现数字字段
  • 使用枚举时,尽量使用枚举字段的名称,而不使用真实的值

模块化

配置名称含义
module设置编译结果中使用的模块化标准
moduleResolution设置解析模块的模式
noImplicitUseStrict编译结果中不包含"use strict"
removeComments编译结果移除注释
noEmitOnError错误时不生成编译结果
esModuleInterop启用es模块化交互非es模块导出

前端领域中的模块化标准:ES6、commonjs、amd、umd、system、esnext
TS中的模块化语句

TS中如何书写模块化语句

  • TS中导入和导出模块,统一使用ES6模块化标准

TS中如何书写Commonjs

导出:export = ???
导入:import ??? = require(‘???’)

接口和类型兼容性

扩展类型-接口

扩展类型:类型别名、枚举、接口、类

TypeScript的接口:用于约束类、对象、函数的标准

  1. 接口约束对象
  // 类型别名
  //  type User = {
  //   name: string
  //   age: number
  //  }
  //接口
   interface User {
    name: string,
    age: number
  }

  let u: User = {
    name: 'zhangsan',
    age: 10
  }
  1. 接口约束函数
   // 类型别名
// type Condition = (n: number) => boolean
// 接口
interface Condition {
  (n: number): boolean
}
function sumFun(numbers: number[], callback: Condition) {
  let s = 0
  numbers.forEach(n => {
    if (callback(n)) {
      s += n
    }
  })
  return s
}
console.log('sumFun', sumFun([1, 2, 3, 4], n => n > 3))

接口继承

可以通过接口之间的继承,实现多种接口的组合

interface A {
  T1: string
}
interface B {
  T2: number
}
interface C extends A, B {
  T3: boolean
}
let a: C = {
  T1: '11',
  T2: 22,
  T3: true
}

使用类型别名可以实现类似的组合效果,需要通过&,它表示交叉类型

type A = {
  T1: string
}
type B = {
  T2: number
}
type C = {
  T3: Boolean
} & A & B

let a: C = {
  T1: '11',
  T2: 22,
  T3: true
}

两者的区别:

  • 子接口不能覆盖父接口的成员
  • 交叉类型会把相同成员的类型进行交叉

readonly修饰符

interface User {
  readonly id: string,
  name: string,
  age: number
}

let u: User = {
  id: '1',
  name: 'zhangsan',
  age: 10
}

const arr: readonly number[] = [1, 2, 3]
const arr: ReadonlyArray<number> = [1, 2, 3]

类型兼容性

B->A 如果能完成赋值,则B和A类型兼容

鸭子辨型法(子结构辨型法):目标类型需要某一些特征,赋值的类型只要能满足该特征即可

  • 基本类型:完全匹配
  • 对象类型:鸭子辨型法

类型断言(as):

TypeScript中的类型断言是一种告诉编译器变量类型的方法。它有两种形式:尖括号语法和as语法。尖括号语法在React中会与JSX语法冲突,因此建议使用as语法。

  1. 对象类型(鸭子辨型法)
interface Duck {
  sound: '嘎嘎嘎',
  swin(): void
}

let person = {
  name: '伪装成鸭子的人',
  age: 1,
  // 断言
  sound: '嘎嘎嘎' as '嘎嘎嘎',
  swin() {
    console.log(this.name);
  }
}
// person可以赋值
let duck: Duck = person
  1. 函数类型
  • 参数:传递的参数可少不可多
  • 返回值:要求返回的必须返回,不要求返回的,无所谓

TS中的类

属性

使用属性列表来描述类中的属性

属性的初始化检查

属性的初始化位置:

  1. 构造函数中
  2. 属性默认值

属性可以修饰为可选的

属性可以修饰为只读的

使用访问修饰符

访问修饰符可以控制类中的某个成员的访问权限

  • public:默认的访问修饰符,公开的,所有的代码均可访问
  • private:私有的,只有类的成员可以访问
  • protected:protected 修饰符与 private 修饰符的行为很相似,但有一点不同,protected 成员在派生类中仍然可以访问
class Person {
  readonly id: number // 永远不能改变 + readonly 只读
  name: string
  age: number
  gender: '男' | '女' = '男'
  pid?: string // 可选属性,不会初始化
  private _publishNum: number = 3 // 每天一共可以发布多少篇文章  内部访问
  private _curNum: number = 0 // 当前可以发布的文章数量  内部访问
  constructor(name: string, age: number, gender: '男' | '女') {
      this.id = Math.random()
      this.name = name
      this.age = age
      this.gender = gender
  }
  publish(title:string) {
   if(this._curNum < this._publishNum){
     console.log(this.name + '发布了一篇文章')
     this._curNum++
   }else{
     console.log('今日发布的文章数量已达到上限')
   }
  }
}
const per = new Person('张三', 20)

属性简写:如果参数直接赋值 语法糖 - 加 public 简写

class Person {
  readonly id: number // 永远不能改变 + readonly 只读
  constructor(public name: string, public age: number) {
      this.id = Math.random()
      this.name = name
      this.age = age
  }
}

访问器

作用:用于控制属性的读取和赋值

class User {
    readonly id: number //不能改变
    pid?: string
    constructor(public name: string, private _age: number) {
        this.id = Math.random();
    }
    set age(value: number) {
        if (value < 0) {
            this._age = 0;
        }
        else if (value > 200) {
            this._age = 200;
        }
        else {
            this._age = value;
        }
    }
    get age() {
        return Math.floor(this._age);
    }
}

const u = new User("aa", 22);
u.age = 1.5;
console.log(u.age);

泛型

泛型是一种特殊的类型,它允许我们创建可以在多个类型之间共享的可重用代码块。泛型可以用于函数、类、接口、类型别名等。在函数中,泛型可以用来指定参数类型和返回值类型。

在函数中使用泛型

在函数名之后写上<泛型名称>

  • 很多时候,TS会智能的根据传递的参数,推导出泛型的具体类型
  • 如果无法完成推导,并且有没有传递具体的类型,默认为空对象
  • 泛型设置默认值 <泛型名称 = 类型>

以下代码定义了一个泛型函数identity,它接受一个参数并返回该参数

function identity<T>(arg: T): T {
  return arg;
}

在这个例子中,T是一个类型参数,它可以用来指定arg的类型和返回值的类型。当我们调用identity函数时,我们可以传递任何类型的参数,并且TypeScript会自动推断出arg的类型和返回值的类型。例如:

let output1 = identity<string>("hello"); // output1的类型为string
let output2 = identity<number>(123); // output2的类型为number

在类型别名、接口、类中使用泛型

直接在名称之后写上<泛型名称>

// 类型别名
// type callback<T> = (n: T, i: number) => boolean
// 接口
interface callback<T> {
  (n: T, i: number): boolean
}
// 仿照数组过滤方法
function filter<T>(arr: T[], callback: callback<T>): T[] {
  const newArr: T[] = []
  arr.forEach((n, i) => {
    if (callback(n, i)) {
      newArr.push(n)
    }
  })
  return newArr
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(filter(arr, n => n % 2 !== 0)); //number

类中的泛型

export class ArrayHelper<T> {

  constructor(private arr: T[]) { }
  take(n: number): T[] {
    if (n >= this.arr.length) {
      return this.arr
    }
    const newArr: T[] = []
    for (let i = 0; i < n; i++) {
      newArr.push(this.arr[i])
    }
    return newArr
  }

  private getRandom(min: number, max: number) {
    const dec = max - min
    return Math.floor(Math.random() * dec + min)
  }
  shuffle() {
    for (let i = 0; i < this.arr.length; i++) {
      const targetIndex = this.getRandom(0, this.arr.length)
      const temp = this.arr[i]
      this.arr[i] = this.arr[targetIndex]
      this.arr[targetIndex] = temp
    }
  }
}

// 类的泛型
const helper = new ArrayHelper<number>([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])  // number

泛型约束

用于限制泛型的取值

// 泛型约束
interface hasNameProperty {
  name: string
}
/**
 * 将某个对象的name属性的每个单词的首字母大写,然后将该对象返回
 */
function nameToUpperCase<T extends hasNameProperty>(obj: T): T {
  obj.name = obj.name.split(' ').map(s => s[0].toUpperCase() + s.substring(1)).join(' ')
  return obj
}

const o = {
  name: '张三',
  age: 23,
  gender: '男'
}

const newO = nameToUpperCase(o)
console.log(newO.name); 

多泛型

// 将两个数组进行混合 [1,2,3] + ['a','b','c'] = [1,'a',2,'b',3,'c']

function mixinArray<T, K>(arr1: T[], arr2: K[]): (T | K)[] {
  if (arr1.length != arr2.length) {
    console.log('两个数组长度不一样');
  }
  let result: (T | K)[] = []
  for (let i = 0; i < arr1.length; i++) {
    result.push(arr1[i])
    result.push(arr2[i])
  }
  return result
}

const arr1 = [1, 2, 3]
const arr2 = ['a', 'b', 'c']

mixinArray(arr1, arr2) //(string | number)
### 回答1: 1. 安装TypeScript:使用 npm 命令 "npm install -g typescript" 安装 TypeScript。 2. 创建TypeScript文件:创建一个名为 "main.ts" 的文件,在其中编写 TypeScript 代码。 3. 编译TypeScript文件:使用命令 "tsc main.ts" 编译 TypeScript 文件,生成同名的 JavaScript 文件。 4. 运行JavaScript文件:使用命令 "node main.js" 运行编译生成的 JavaScript 文件。 5. 添加类型注解:在变量前加上类型注解,如 "let message: string = 'Hello World'"。 6. 添加类型检查:使用 "tsc --noEmit" 命令只进行类型检查而不生成 JavaScript 文件。 这些步骤可以帮助你在5分钟内快速上手 TypeScript。 ### 回答2: TypeScript是一种静态类型的编程语言,它是JavaScript的超集。要快速上手TypeScript,你可以按照以下步骤进行: 1. 安装TypeScript:首先,你需要在你的计算机上安装TypeScript。你可以使用Node.js包管理器(npm)或者使用TypeScript官方提供的安装包进行安装。 2. 创建TypeScript文件:在你的项目目录下,创建一个以`.ts`扩展名结尾的TypeScript文件。例如,你可以创建一个名为`example.ts`的文件。 3. 编写TypeScript代码:在刚才创建的TypeScript文件中,你可以使用JavaScript的语法以及TypeScript的类型注解来编写代码。TypeScript提供了一些新的语法和特性,例如类、接口、泛型等。 4. 编译TypeScript代码:在终端中,进入到你的项目目录,并使用TypeScript编译器(tsc)将TypeScript代码编译成JavaScript代码。你可以使用以下命令进行编译: ``` tsc example.ts ``` 5. 运行JavaScript代码:在编译成功后,你将得到一个与TypeScript文件同名的JavaScript文件(`example.js`)。你可以使用Node.js或者在浏览器中运行该JavaScript文件来查看结果。 以上就是使用TypeScript快速上手的基本步骤。当你熟悉了TypeScript的基本语法和特性后,你可以进一步学习TypeScript的高级特性,如模块化、异步编程等。还可以结合一些TypeScript开发工具,如编辑器插件、调试工具等,来提升你的开发效率。 ### 回答3: 要快速上手TypeScript,你可以按照以下步骤进行操作: 1. 安装TypeScript:首先,你需要在你的计算机上安装TypeScript编译器。你可以通过npm(Node Package Manager)来安装它,使用下面的命令: ``` npm install -g typescript ``` 2. 创建一个TypeScript文件:在你的项目中,创建一个后缀名为`.ts`的TypeScript文件。 3. 确定编译选项:在你的项目根目录下创建一个`tsconfig.json`文件,用于配置TypeScript编译器的选项。你可以根据需要选择不同的选项,比如目标版本、模块系统等。 4. 编写TypeScript代码:在TypeScript文件中编写你的代码。TypeScript是一种强类型的编程语言,它提供了类、接口、枚举等丰富的语言特性。 5. 编译TypeScript代码:使用以下命令将你的TypeScript代码编译为JavaScript代码: ``` tsc ``` 6. 运行JavaScript代码:在编译成功后,你将得到一个后缀名为`.js`的JavaScript文件。你可以使用任何支持JavaScript的环境(如浏览器、Node.js等)来运行这些代码。 7. 运行时类型检查:TypeScript还提供了运行时类型检查的功能。你可以使用像`typeof`、`instanceof`等运算符来进行类型检查,确保程序的运行过程中类型的正确性。 通过按照上述步骤进行操作,你就可以快速上手TypeScript,并开始使用它来开发你的项目了。当然,为了更好地掌握TypeScript的更高级特性和最佳实践,你可能需要进一步学习和实践。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值