TypeScript知识点

本文探讨了TypeScript和Flow在强类型与弱类型、静态类型与动态类型的区别,强调了强类型的优势,如早期错误检测和代码准确性。同时介绍了Flow的安装、使用和类型注解,以及TypeScript的基本应用,包括类型声明、接口和泛型等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

强类型与弱类型(类型安全)

强类型

  语言层面限制函数的实参类型必须与形参类型相同。可以理解为强类型语言中不允许有任意的数据隐式类型转换。

弱类型

  弱类型语言层面不会限制实参的类型。可以理解为弱类型语言中允许任意的数据隐式类型转换。

静态类型与动态类型(类型检查)

静态类型

  一个变量在声明时类型就是明确的,声明过后,它的类型就不允许被修改

动态类型

  运行阶段才能确定变量的类型,并且变量的类型随时可以改变。

JavaScript自有类型系统的问题

  JavaScript是动态类型的弱类型语言,JavaScript没有编译环节。

弱类型带来的问题

  1.程序运行时的类型异常需要等到执行的时候才能发现,如:

const obj = {};
obj.foo(); // 运行时才会抛出错误

  2。类型不明确造成函数功能不是原本想要实现的功能。 如:

function sum(a, b){
	return a + b;
}
sum(100, 100); // 正常程序需要的结果
sum(100, '100'); // 不是自己想要的方法   

  3.对对象索引器错误的用法。如:

const obj = {};
obj[true] = 100;
console.log(obj['true']);        

强类型的优势

  1.错误更早暴露,不会像弱类型一样等到运行时才报错。
  2.代码更智能,编码更准确。就好比智能提示可以根据你的输入进行准确的判断,而不会出现像弱类型无法根据类型进行智能提示。
  3.重构更牢靠,例如定义了一个属性或方法,在后续想要进行更改的时候,弱类型语言无法及时体现出错误,对重构的速度影响很大。
  4.减少不必要的类型判断。例如上面提到的sum函数,要进行准确的功能实现,就需要对传入的形参值进行类型的判断,这样子就会增加了不必要的代码。

Flow静态类型检查方案

  Flow是JavaScript的类型检查器。

简单安装及使用

  初始化项目

yarn init --yes

  安装flow-bin,安装在局部即可。

yarn add flow-bin --dev

  安装完成后对flow进行初始化。

yarn flow init

  然后便可以执行flow检查,以如下代码为例:

// @flow
function sum(a: number, b: number){
    return a + b;
}

sum(100, 100);
sum('100',100)

  这里需要注意要执行flow检查的代码需要在之前加入// @flow的标志,这里使用flow检查就会报错:
在这里插入图片描述
  但是实际使用时,上述代码使用了类型注解会进行报错,因此我们需要将其自动移除。这里就需要安装一个模块:

yarn add flow-remove-types --dev

  简单使用:

yarn flow-remove-types . -d dist

  当然也可以配合babel使用:

yarn add @babel/core @babel/cli @babel/preset-flow
yarn babel src -d dist

安装开发工具插件

  安装flow language support。

类型推断

  例如如下代码:

/* 类型推断
* @flow
*/

function squre(n){
    return n * n;
}

squre('100')

  这里虽然没有为n添加类型注解,但是字符串显然不能相乘,因此这边代码也会在return语句进行报错。

类型注解

  除了上述使用到的函数形参使用的类型注解外,类型注解还可以使用在变量和函数的返回值上,例如:

let a: number = 100
function foo(): number{
	return 100
}

  这边需要注意的是,若函数没有返回值,则应该设置为void。

原始类型

  这里的原始类型和js的类似:

const a: string = '123'
const b: number = NaN
const c: boolean = false
const d: null = null
const e: void = undefined
const f: symbol = Symbol()

数组类型

  可以通过泛型指定,或是通过方括号的方式指定。

const arr: Array<number> = [1,2,3]
const arr1: number[] = [1,2,3]
// 元组
const foo: [string, number] = ['111', 111]

对象类型

const obj1: { foo: string, bar: number} = { foo: '123', bar: 100}
const obj2: { foo?: string, bar: number} = { bar: 100}
const obj3: { [string]: string } = {}

obj3.key1 = 'value1'
obj3.key2 = 'value2'

函数类型

function foo(callback: (string, number) => void){
    callback('string', 1000)
}

foo(function(str, n){
    // str => string
    // n => number
})

特殊类型

const a : '123' = '123'
const type: 'success' | 'warning' | 'danger' = 'success'
type StringOrNumber = string | number
const b: StringOrNumber = 123

const gender: ?number = undefined // 这里的?number相当于number | null | undefined

任意类型

Mixed

// mixed可以理解为任意类型,如string、number等等
function passMixed(value: mixed){
    value.substr(1);
    value * value
}

Any


// any也是可以为任意类型
function passAny(value: any){
    value.substr(1);
    value * value
}

区别

  不同的是,any表示的是弱类型,mixed代表的是强类型,如上述相同的代码,使用mixed就会报错。

TypeScript语言规范与基本应用

基本使用

  安装

yarn add typescript --dev

  编译使用

yarn tsc demo01.ts

配置文件

  安装项目运行配置。

yarn tsc --init

标准库声明

  标准库就是内置对象所对应的声明,其实就是生成的tsconfig.json里的target属性,例如设置为es5的话,这时候使用es6的语法就会报错,而设置成es2015则不会。或者通过设置lib也可以:

"lib": ["ES2015","DOM"],  

中文错误消息提示

yarn tsc --locale zh-CN

作用域问题

  例如在其中一个ts文件中定义了一个const变量,然后在另一个文件中重复定义,就会报错。解决办法:1.可以使用立即执行函数等创建一个新的作用域;2.也可以通过export {},创建一个模块化的作用域。

object类型

  ts中的object类型可以指对象、数组或是函数。

枚举类型

  使用enum关键字定义:

enum PostStatus{
    Draft = 0,
    Unpublished = 1,
    Published = 2
}

const post = {
    title: 'hello ts',
    content: 'hello world',
    status: PostStatus.Draft
}

  这里需要注意的是,如果enum中的字段没有定义值或是只定义部分的值,后续的值都是依次加一。当然枚举类型也可以是字符串,但是使用字符串,必须每个都要赋值。

隐式类型推断

  其实就是事先不为变量添加类型注解,但是在赋值时,ts会隐式地进行类型的推断:

let age = 18 // 隐式推断为number
let str = 'string' // 隐式推断为string

类型断言

  就是告诉ts自身定义的变量一定会是某种类型,例如:

const nums = [1,2,3,4]
const res = nums.find(i => i > 0)
const square = res * res

  上述代码是会报错的,因为ts并不知道你res值一定是number,但如果进行了类型断言就不会发生报错:

const nums = [1,2,3,4]
const res = nums.find(i => i > 0)
// const num1 = res as number
const num1 = <number> res

const square = num1 * num1

  类型断言一共有两种方式,但建议使用as。

接口

  就是用来约束对象的结构,如果要实现接口,就一定要拥有这个接口的所有成员,当然也可以通过?设置可选成员。

interface People{
    name: string
    age: number
    desc?: string
    readonly id: string // 表示只读成员,不能进行修改
}

function getPer(people: People){
    console.log(people.name)
    console.log(people.age)
}

getPer({
    name: 'lily',
    age: 18,
    id: '123'
})

  接口还可以进行动态的定义,例如:

interface Stu {
    [prop: string]: string | number
}

const stu: Stu = {}

stu.name = 'zhangsan'
stu.age = 18

类的使用

  ts中的类与es6类似:

class Person {
    name: string
    age: number
    constructor (name: string, age: number){
        this.name = 'zhangsan'
        this.age = 18
    }
}

  不同的是,这里的属性必须要进行初始化。并且ts中有访问修饰符,同java的public、private和proteced。还可以设置类的属性为只读。

类与接口

interface run {
    run(distance: number) : void
}

interface eat {
    eat(food: string) : void
}

class People implements run, eat{
    run(num: number) {
        console.log(num)
    }
    eat(str: string) {
        console.log(str)
    }
}

class Animal implements run, eat{
    run(num: number) {
        console.log(num)
    }
    eat(str: string) {
        console.log(str)
    }
}

抽象类

export {}
abstract class Animal {
    run(dis: number): void {
        console.log(dis)
    }
    abstract eat(food: string): void 
}

class People extends Animal {
    eat(str: string) {
        console.log(str)
    }
}

  在抽象类中,可以定义普通方法和抽象方法,但是抽象方法在子类中一定要实现。

泛型

function createArray<T>(length: number, value: T): T[] {
    const arr = Array<T>(length).fill(value)
    return arr
}

console.log(createArray<number>(10, 10))

console.log(createArray<string>(5, '123'))

类型声明

  使用declare声明:

declare function camelCase (input: string): string
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这名没人用吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值