大前端进击之路(四)TypeScript入门基础

在这里插入图片描述

打工人!打工魂!前端才是人上人!此系列总结于大前端进击之路过程中的学习,如果文章中有不对的地方,希望大家能进行批评改正,互相进步。转载请注明出处。

语言类型

类型安全

  • 强类型

在语言层面限制函数的实参类型必须与形参类型相同,不允许任意的隐式类型转换。

  • 弱类型

弱类型不限制实参的类型,允许任意的隐式类型转换。

funciton sum(a, b) {
    console.log(a + b)
}
sum(1,2)  // 打印 3
sum(1,'a') //打印 1a

类型系统

  • 静态类型

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

  • 动态类型

变量的类型随时可以改变,运行阶段才能明确变量类型,变量没有类型,变量存放的值是有类型的。

var a 
a = 'hello'
console.log(a)  // hello
a = 123
console.log(a)  // 123

JavaScript自有类型系统的问题

通过上面我们了解了强类型和弱类型、动态类型和静态类型,我们可以知道JavaScript语言是弱类型、动态类型的。这是因为早期JavaScript编写的应用比较简单,没有编译环节。类似上面的例子我们写了一个两个数相加的sum函数,我们只是想要让两个数字相加,但是如果我们参数输入了字符串,得到的结果就会是字符串拼接。这就是弱类型的问题,让我们的代码不可靠,不能及时发现问题。

强类型的优势

  • 错误更早暴露
  • 编码更准确,代码更加智能
  • 重构更可靠
  • 减少不必要的类型判断

TypeScript基础

TypeScript是什么?

TypeScript是一种由微软开发的自由、开源的编程语言。它是JavaScript的一个超集,本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。任何一个JavaScript运行环境都支持它,TypeScript提供最新的和不断发展的JavaScript特性,功能更加强大,生态也更健全、更完善。

在这里插入图片描述
在这里插入图片描述

缺点:

  • 项目初期,使用TypeScript会增加成本。
  • 语言本身相对于JavaScript多出一些新的概念,增加学习成本。

但是TypeScript是渐进式的,我们会使用JavaScript的语法可直接上手TypeScript。

TypeScript初体验

安装TypeScript
npm install -g typescript
配置文件

生成配置文件tsconfig.json

tsc --init

在这里插入图片描述

// 在生成的配置文件中比较常用的配置选项
// target  => 编译目标为es5
// lib     => 标准库声明,这里我们引用了ES2015、DOM、ES2017
// outDir  => 编译后文件存放位置
// rootDir => 文件根路径
编译TypeScript文件
// 如果我们配置好tsconfig.json文件后可直接使用tsc命令编译
tsc

// 如果我们没有配置好tsconfig.json文件
tsc xxx.ts
// 会给我们生成xxx.js

作用域问题

在TypeScript中会默认文件中的成员会作为全局成员,如果多个文件中有多个相同成员就会出现冲突。

解决办法:

  1. 使用IIFE提供独立作用域
(function () {
    const a = 123
}())
  1. 在当前文件使用export,也就是把当前文件变成一个模块,模块具有单独的作用域。
const a = 123
export {}

基本数据类型

原始数据类型

基础类型分为string、number、boolean、null、undefined、Symbol、void。

const str:string = 'string'
const num:number = 1
const boo:boolean = true
const n:null = null
const u:undefined = undefined
const s:Symbol = Symbol()
const v:void = undefined
Object类型

Object是指除了原始数据类型以外的其它类型

const fun:object = function () {}

const obj:{name:string, age:number} = {
    name : 'xm',
    age : 25
}
Array类型
// 1.可以在元素类型后面街上[],表示由此类型元素组成的一个数组
let arr : number[] = [1,2,3]
// 2.也可以使用数组泛型
let arr : Array<number> = [1,2,3]
元祖Tuple

元祖类型表示一个规定好元素数量和类型的数组。

let arr : [string, number] = ['xm',20]
枚举Enum

使用枚举我们可以定义一些带名字的敞亮,可以清晰的表达意图或创建一组有区别的用例。分为数字枚举和字符串枚举。

数字枚举
enum Direction {
    Up = 1,
    Down,
    Left,
    Right
}
// Up的初始值为1,其余的成员会从1开始自动增长。Down为2,Left为3,Right为4
字符串枚举

字符串枚举并没有自增长的行为,但是可以很好的序列化。

enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}
函数类型

我们可以为一个函数的返回值设定类型

function sum(a: number, b: number): number {
    return a + b
}
sum(1, 2)
// 我们为sum函数的两个参数设定为number类型,返回结果也设定位number类型
可选参数和默认参数

在TypeScript中我们可以在参数名旁使用?实现可选参数的功能,可选参数和默认参数必须跟在必须在最后

// 可选参数
function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

// 默认参数
function buildName(firstName: string, lastName:string = "xm") {
    // ...
}
任意类型any

任意类型我们也可以成它为弱类型,意思就是任意类型都可以。

let foo: any = 'string'
foo = 100
foo.bar()
隐式类型转换

在TypeScript中存在隐式类型转换,因此建议我们为每个变量都添加明确的类型。

let age = 18   // number
age = 'string' // 报错

let foo        // 不声明类型
foo = 100      // 默认为任意类型any
foo = 'string' // 不报错
类型断言

类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构,没有运行时的影响,只是在编译阶段起作用。就好比我们告诉TypeScript,相信我,我知道这个变量的类型是什么,我知道自己正在干什么。

// 假定这个 nums 来自一个明确的接口
const nums = [110, 120, 119, 112]
const res = nums.find(i => i > 0)
const square = res * res // 在这里会报错,因为TypeScript不确定res的类型是什么,const res: number | undefined

// 使用类型断言 两种方式是一样的
const num1 = res as number
const num2 = <number>res  // 这种方式在JSX下不能使用

接口interface

定义一些结构,我们去使用这个接口就必须去遵守这些接口所定义的结构。

interface Post {
  title: string
  content?: string  // ?代表可选成员
  readonlys summary: string // 只读属性
}

function printPost (post: Post) {
  console.log(post.title)
  console.log(post.content)
}

printPost({
  title: 'Hello TypeScript',
  content: 'A javascript superset'// 可选
  summary: 'hello'  // 只读无法修改
})

// 动态成员
interface Cache {
  [prop: string]: string 
}

const cache: Cache = {}

cache.foo = 'value1'
cache.bar = 'value2'

类class

class Person {
    // 类的属性需要使用的话,需要明确声明类型
    name: string
    age: number
    
    constructor (name: string, age: number) {
        this.name = name
        this.age = age
    }
	sayHi (msy: string): void {
        console.log(`我是${this.name},${msg}`)
    }
    
}
类的访问修饰符
  • 默认为public公共属性
  • private是私有属性,外部无法访问
  • protected受保护的,与private很相似,外部也无法访问,但是在派生类中可以被访问
  • readonly只读属性
  • 构造函数也可以被设置为private、protected
class Person {
    private name: string
    protected readonly age: number
    
    constructor (name: string, age: number) {
        this.name = name
        this.age = age
    }
	sayHi (msy: string): void {
        console.log(`我是${this.name},${msg}`)
    }
    
}

类和接口

interface Eat {
    eat(foot: string): void
}
interface Run {
    run(distance: number): void
}
class Person implements Eat, Run {
    eat(food: string): void {

    }
    run(distance: number): void {

    }
}
class Animal implements Eat {
    eat(food: string): void {

    }
}

抽象类

抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log('roaming the earch...');
    }
    // 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现
    abstract run (distance: number): void
}

泛型

function createNumberArray(length: number, value: number): number[] {
    const arr = Array<number>(length).fill(value)
    return arr
}
// 上面这个函数只能创建数字类型的数组,我们要是想要创建一个字符串类型的数组,又得写一个函数,这时候我们可以使用泛型
function createArray<T>(length: number, value: T): T[] {
    const arr = Array<T>(length).fill(value)
    return arr
}
const res = createNumberArray(3, 100)
const numArr = createArray(3, 'you')
const strArr = createArray(3, 100)

类型声明

import { camelCase } from 'lodash'

declare function camelCase (input: string): string

const res = camelCase('hello typed')

// 也可以使用npm install @types/lodash --dev 添加类型声明模块

历史文章传送门

参考

拉勾大前端训练营

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值