TS初学笔记

2021-07-30  本文已影响0人  YukiWeng

整理之前学习ts时的一些笔记。


安装
npm install -g typescript // 报无权限 
sudo npm install -g typescript 
tsc -v // tsc,ts编译器,查看版本
// hello.ts 
const hello = (name:string)=>{ return `hello ${name}` } 
hello('yuki')
tsc hello.ts  //编译 ===> 生成 hello.js
tsc -w hello.ts //监听hello.ts 的变化
node hello.js //运行 js 文件

或者安装 ts-node ,将以上两步合并为一步 ts-node hello.ts

编译后,函数会出现(2393)函数实现重复,猜测可能是vscode的bug(不确定)
在项目根目录添加配置文件 tsconfig.json即可(空文件也可)


基础类型
let isDone: boolean = false;
let age: number = 18; 
let firstName: string = "yuki"; 
let message: string = `Hello,${firstName},age is ${age}`; 
let u: undefined = undefined; 
let n: null = null; 
let num: number = undefined;
any 和 联合类型
let notSure: any = 4; 
notSure = "a string"; 
notSure = true; 
notSure.getName(); 

let numberOrString: number | string; 
numberOrString = "hhh"; 
numberOrString = 1;
数组Array 和 元祖Tuple
// 数组 Array 
let arrOfNumbers: number[]=[1,2,3] 
arrOfNumbers.push(5) 

// 元祖 Tuple
let user:[string,number]=['1',3]
interface 接口

对象的形状(shape)进行描述
类(class)进行抽象

interface Person { 
  readonly id:number, // readonly 用于对象属性,不允许修改该值 
  name: string; 
  age?: number; // ? 表示 非必须 
} 
let yuki: Person = { 
  id:1111, 
  name: "yuki",
  age: 20, // 此处允许不加age 
};
 yuki.id = 2222 // error , id readonly,不允许修改
函数 和 类型推断

如下,
z 为可选参数。需要注意,必选参数 必须放在 可选参数 之前,否则报错
或者用es6的写法, z:number = 0 ,不传的话默认为0

// function add ():number{} 此处的number 规定了输出的类型为number
function add(x:number,y:number,z?:number):number{ 
  if(typeof z ==='number'){ 
    return x+y+z 
  } 
  return x+y 
} 
let result1 = add(1,2,3) 
let result2 = add(1,2)

注意,下图中,不是es6中的箭头函数。而是tsc(ts编译器)的 类型推断

image.png
let str= 'str' 
str= 123 // error , 因为ts推断出 str 是string类型
Class 类

默认是public,允许外部和子类访问
private 不允许外部和子类访问
protected 不允许外部访问,允许子类访问
readonly 可访问,不可修改

class Animal { 
  private name:string 
  constructor(name:string){ 
    this.name=name
  }
} 
const snake = new Animal('lili') 
console.log(snake.name) // error,外部不允许访问 
snake.name='lucy' // error,外部不允许访问 

class Dog extends Animal { 
  break() { 
    return `${this.name} is barking`; // error 子类同样无法访问
  }
 }

子类继承父类,复杂场景时可能无法满足需求,故,可用接口interface提供公共部分
类可以同时继承多个接口,implements (类继承接口就必须实现这个接口里面写的方法)
接口可以继承接口,extends

interface Radio { 
  switchRadio():void // void 什么都不返回
} 
interface Battery{ 
  checkBatteryStatus() 
} 

// 方法一:CellPhone 同时implements Radio,Battery 
class Car implements Radio { 
  switchRadio(){ } 
} 
class CellPhone implements Radio,Battery{ 
  switchRadio(){ } 
  checkBatteryStatus(){ } 
} 

// 方法二:RadioWithBattery 继承 Radio, CellPhone implements RadioWithBattery 
interface RadioWithBattery extends Radio{ 
  checkBatteryStatus(){ } // 继承了Radio的switchRadio(){ } ,并添加checkBatteryStatus(){ } 
}
class CellPhone implements RadioWithBattery{ 
  switchRadio(){ } 
  checkBatteryStatus(){ } 
}
Enum 枚举

默认从0开始赋值,每个值自动递增
也可以自行赋值,numberstring 等均可

enum Direction { 
  Up, // 若 赋值 Up=10,则Down为11, Direction[10]为Up 
  Down,
  Left,
  Right
} 
console.log(Direction.Up) // 0 
console.log(Direction[0]) // 'Up'   双向

编译后,可发现转为js后,是一个自执行函数

// js 
var Direction; 
(function (Direction) { 
  Direction[Direction["Up"] = 0] = "Up";
  Direction[Direction["Down"] = 1] = "Down"; 
  Direction[Direction["Left"] = 2] = "Left";
  Direction[Direction["Right"] = 3] = "Right"; 
})(Direction || (Direction = {}));

常量枚举(加const)

const enum Direction { 
  Up = 'up', 
  Down = 'down' 
} 
const value = 'up' 
console.log(value === Direction.Up) // true

编译后:

// js 
var value = "up"; 
console.log(value === "up" /* Up */);

常量枚举成员在使用的地方会被内联进来,
之所以可以这么做是因为,常量枚举不允许包含计算成员;
如上,编译时,并没有 Direction 变量的,因此常量枚举会对性能有一定提升。

泛型 (一)

如下,自定义一个泛型T,函数入参类型T,出参同样T(使入参出参保持一样的类型)
当入参为string,出参同样是string;入参为number,出参同样number

function echo<T>(arg: T): T {
  return arg;
} 
const res = echo("str"); 

function swap<T, U>(tuple: [T, U]): [U, T] { 
  return [tuple[1], tuple[0]]; 
} 
const res2 = swap(["str", 123]);
泛型(二):约束泛型
interface IwithLength { length: number; } // 入参必须包含 length属性
function echoWithLength<T extends IwithLength>(arg: T): T {
  console.log(arg.length); 
  return arg; 
} 
const arr = echoWithLength([1, 2]); 
const obj = echoWithLength({ x: 1, length: 1 }); 
const str = echoWithLength('hhh')
泛型(三):类和接口
class Queue<T> { 
  private data = []; 
  push(item: T) { 
    return this.data.push(item);
  } 
  pop(): T { 
    return this.data.shift(); 
  } 
} 

const queue = new Queue<number>(); 
queue.push(1); 
console.log(queue.pop().toFixed()); 

const queue2 =new Queue<string>() 
queue2.push('str') 
console.log(queue2.pop())
interface Iplus<T> { 
  (a: T, b: T): T; // 函数,入参一和入参二为T,出参为T 
} 
function plus(a: number, b: number): number { 
  return a + b; 
} 
function connect(a: string, b: string): string { 
  return a + b; 
} 
const num: Iplus<number> = plus; 
const str: Iplus<string> = connect;

当我新建另一个ts文件:

let isDone: boolean = false 
//报错,提示 'isDone' was also declared here.

在默认状态下,typescript 将 DOM typings 作为全局的运行环境,
当我声明 isDone 时, 与 DOM 中的全局 window 对象下的isDone属性出现了重名。

解决方法:在脚本文件最后一行,添加 export {}; 将文件声明为模块
(在 Typescript 中,只要文件存在 import 或 export 关键字,都被视为 module)


类型别名

使用关键字type,多用于联合

type PlusType = (x: number, y: number) => number; 
function sum(x: number, y: number): number { 
  return x + y; 
} 
const sum2: PlusType = sum; // 代替 const sum2: (x: number, y: number) => number = sum
类型断言

通过类型断言这种方式告诉编译器类型,只在编译阶段起作用

let someVal: any = 'str' 
let strLength: number = (<string>someVal).length // 尖括号 
let strLength2: number = (someVal as string).length // JSX 只可使用as语法断言
声明文件

https://www.runoob.com/typescript/ts-ambient.html

目的:为了借用 TypeScript 的各种特性来使用第三方库文件
(declare 定义的类型只会用于编译时的检查,编译结果中会被删除。)

如,

declare var jQuery:(selector:string)=>any

把这些声明单独放在一个文件,称为声明文件,以 .d.ts 为后缀,如 jQuery.d.ts
一般而言,所有ts文件都可获得这些类型定义,若无法获取,可在根路径的tsconfig.json中配置tsc编译器

{ "include":["**/*"] }

DefinitelyTyped (http://definitelytyped.org/
该组织提供了各类声明文件,安装即可,无需自己创建声明文件

npm install --save-dev @types/jquery
上一篇下一篇

猜你喜欢

热点阅读