typescript基础
2020-06-06 本文已影响0人
noyanse
/**
* @description 原始数据类型
*/
let isDone: boolean = false
let age: number = 20
// 二进制
let binaryNumber: number = 0b1111
let firstName: string = 'hello'
// 模版字符串
let message: string = `my name is ${firstName}`
// undefined 和 null 是所有类型的子类型
let u: undefined = undefined
let n: null = null
let num: number = undefined // number类型可以赋值为 undefined
/**
* @description any类型 和 联合类型 |
*/
// 无法确定是什么类型 any 允许赋值为任意类型
// 当有明确类型时,不要用any
let notSure: any = 3
notSure = 'string'
// notSure.getName() // 可以调用方法 也没有报错
// 允许一部分类型 | 表示联合类型
let numberOrString: number | string = 123
/**
* @description array 和 tuple
*/
// 定义数组里面元素的类型
let arrOfNumbers: number[] = [1, 3, 4]
arrOfNumbers.push(5) // 数组的方法也会限制
// 类数组
function test() {
console.log(arguments) // 类数组,有数组的一定属性
// 但是没有数组的方法
// let htmlCollection: NodeList
}
// 数组将同一种类型的数据聚合到一起
// 不同类型的数据用tuple
let tupleArr: [string, number] = ['hello', 1]
/**
* @description interface接口
* 定义js中 对象类型
* 1 对对象的形状(shape)进行描述 如属性方法
* 2 对类进行抽象 duck typing
*
* 首字母一般大写
*/
interface Persons {
readonly id: number // 只读 不可再次赋值 readonly 用在属性上 const用在变量上,二者相似
name: String
age?: Number
}
let viking: Persons = {
id: 1,
name: 'argen',
}
/**
* @description 函数 和 类型推断
*/
// 函数声明写法
function add (x: number, y: number): number {
return x + y
}
let result = add(2, 3)
// 可选参数 只能放最后
function add1 (x: number, y: number, z?: number): number {
if (typeof z === 'number') {
return x + y + z
}
return x + y
}
// 可选参数还可用es6的默认值写法
function add2 (x: number, y: number, z: number = 10): number {
if (typeof z === 'number') {
return x + y + z
}
return x + y
}
let result1 = add1(2, 3)
let result2 = add1(2, 3, 4)
// 函数表达式写法
// add3也是有类型的,是个函数类型
const add3 = function (x: number, y: number, z: number = 10): number {
if (typeof z === 'number') {
return x + y + z
}
return x + y
}
// ts直接推断出add3是函数类型
const add4: (x: number, y: number, z?: number) => number = add
/**
* @description class
*/
class Animal {
public name: string
constructor (name: string) {
this.name = name
}
run () {
return `${this.name} is running`
}
}
const snake = new Animal('snake')
console.log(snake.run())
// 继承 拥有了父类的属性和方法,并且有了自己的方法
class Dog extends Animal {
bark () {
return `${this.name} is barking`
}
}
const dog = new Dog('dog')
console.log(dog.bark())
// 继承 方法重写
class Cat extends Animal {
constructor (name) {
super(name)
console.log(this.name)
}
run () {
return `miaomiao - ` + super.run()
}
}
const cat = new Cat('cat')
console.log(cat.run())
/**
* @description 修饰符
* public
* pravite 只能自己访问,子类也不能调用
* protected 只有自己和子类可以访问
* readonly 只能读 不能写
* 静态属性和方法 不需要实例化 可直接调用
* static 和
*/
class Animal1 {
public name: string
static categories: string[] = ['animal', 'bird']
static isAnimal (a) {
return a instanceof Animal1
}
constructor (name: string) {
this.name = name
}
run () {
return `${this.name} is running`
}
}
const lion = new Animal1('lion')
console.log(lion.run())
console.log(Animal1.categories)
console.log(Animal1.isAnimal(lion))
/**
* @description 类和接口
* 接口对类的一部分类型进行抽象
* 类 实现 接口
*/
interface Radio {
// 参数和返回值类型定义
switchRadio (): void
}
interface Battery {
checkBatteryStatus()
}
// 接口之间可以有继承关系, 合并Radio 和 Batter接口
interface RadioWithBattery extends Radio {
checkBatteryStatus()
}
// 通过 interface告诉手机和汽车都要实现这个功能
class Car implements Radio {
switchRadio () {
}
}
class Cellphone implements Radio, Battery {
switchRadio () {
}
checkBatteryStatus () {
}
}
class Cellphone1 implements RadioWithBattery {
switchRadio () {
}
checkBatteryStatus () {
}
}
/**
* @description 枚举 Enum
* 一系列常量
*/
enum Direction {
Up = 10, // 接下来的项会递增
Down,
Left,
Right
}
console.log(Direction.Up)
console.log(Direction[10])
// 加一个 const 就是一个常量枚举 提升性能
// 只有常量值可以作为常量枚举
const enum Direction1 {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
const value1 = 'UP'
if (value1 === Direction1.Up) {
console.log('go up')
}
/**
* @description 泛型 Generics
* ts最难的点
* 解决怎么样的问题:
* 函数参数的值类型与返回类型统一
* <> 尖括号里面写泛型的名称 相当于一个占位符
*/
function echo <T> (arg: T): T {
return arg
}
const resultEcho: string = echo('str')
console.log(resultEcho)
// 调换一下位置,返回2项
function swap<T, U> (tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]]
}
const resSwap = swap(['string', 123])
console.log(resSwap)
/**
* @description 约束泛型
*/
// 事先不知道参数什么类型,所以不能使用它的方法
function echoWithArr<T> (arr: T): T {
// console.log(arr.length)
return arr
}
// 设定是数组,才能使用数组的方法 返回也是T[]
function echoWithArr1<T> (arr: T[]): T[] {
console.log(arr.length)
return arr
}
const arrs = echoWithArr1([1, 2, 3])
// 对泛型约束 定义一个接口,extends这个接口
interface IWithLength {
length: number
}
function echoWithLength<T extends IWithLength> (arg: T) : T {
console.log(arg.length)
return arg
}
// 只要有length属性,就符合这个约束,duck typing啦⁄⁄⁄⁄⁄
const str = echoWithLength('str')
const obj = echoWithLength({ length: 10})
const arr2 = echoWithLength([1, 2, 3])
/**
* @description 泛型在其他场景重的使用
*/
class Queue {
private data = []
push (item) {
return this.data.push(item)
}
pop () {
return this.data.shift()
}
}
const queue = new Queue()
// 可以push各种类型的值
queue.push(1)
queue.push('str')
// 运行的时候会捕获错误,但是ts并没报错
// 这里只调用数字上的方法会报错
console.log(queue.pop().toFixed())
console.log(queue.pop().toFixed())
// 解决方法1 不实用
class Queue1 {
private data = []
push (item: number) {
return this.data.push(item)
}
pop (): number {
return this.data.shift()
}
}
// 解决方法2 希望传入什么输出什么 用泛型
// 在实力化的时候约定参数类型
class Queue2<T> {
private data = []
push (item: T) {
return this.data.push(item)
}
pop (): T {
return this.data.shift()
}
}
const queue2 = new Queue2<number>()
queue2.push(1)
// queue2.push('str') // 这里就会报错了
// interface用泛型描述
interface KeyPair<T, U> {
key: T
value: U
}
let kp1: KeyPair<number, string> = {
key: 1,
value: 'str'
}
// 描述数组
let arr: number[] = [1, 2, 3]
// 可以也成
let arrTwo: Array<number> = [1, 2, 4]
// 描述函数
function plus(a: number, b: number): number {
return a + b
}
// 这个接口就比较通用了
interface IPlus<T> {
(a: T, b: T): T
}
const a: IPlus<number> = plus // 此时的a由于类型推断是函数类型
/**
* @description 类型别名和类型断言
* type aliases
*/
function sum (x: number, y: number): number {
return x + y
}
const sum2: (x: number, y: number) => number = sum
// 抽象函数类型
type PlusType = (x: number, y: number) => number
const sum3: PlusType = sum
// 在联合类型下的应用
type NameResolver = () => string
type NameOrResolver = string | NameResolver
function getName (n: NameOrResolver): string {
if (typeof n === 'string') {
return n
} else {
return n()
}
}
// type assertion 类型断言
// 在不知道返回值类型的时候就要使用他的属性和方法
function getLength (input: string | number): number {
// input.length
const str = input as String
if (str.length) {
return str.length
}
// 简单写法
if ((<string>input).length) {
// 整体就变成了一个断言
return (<string>input).length
}
}
/**
* @description 引用第三方库 声明文件
*/
// 通常会把这个放在单独的文件中
declare var jQuery: (selector: string) => any