0
点赞
收藏
分享

微信扫一扫

TS系统整理

为什么需要TypeScript?

TypeScript主要是用于静态类型的检查。使用JS的时候,我们必须要知道各种类型的细节才可以编写正确的代码。

Ts文件和JS文件同时存在出现函数重复问题

TS系统整理_typescript

解决上述问题只需要初始化typescript的配置文件即可。

tsc --init

关闭TS的检查

只需将ts的配置文件中的strict这一行注释掉即可。

持续将TS转换为JS

tsc --watch

显示类型

function test2(person: string,date: Date) {
console.log(`${person}你好,今天是:${date.toDateString()}`);
}

test2('张三',new Date())

常用类型

  1. 基元类型(string,number,boolean)

let str: string = "张三";
let num: number = 20;
let bool: boolean = false;

  1. 数组(type[] 或者 Array[type])

let nums: Array = [1,2,3];
let nums1: number[] = [4,5,6];

  1. any(不希望某个特定的值导致类型检查错误)

let obj: any = {
x: '666'
}
// 下面的这句TS不会报错,但是转换为JS后是不能正常运行的,但是定义为any后可以防止报错
obj.foo()

  1. 函数(主要是对参数和返回值进行注解)

function greet(name: string): void {
console.log('Hello' + name);
}

  1. 对象类型

function printxy(pt: {x: number, y: number}) {
console.log(pt.x,pt.y);
}
printxy({x: 25,y: 26})

  1. 联合类型

let test: number | string = 20;
let test2: numer | string | number[] = 21;
test = '111'

  1. 类型别名

type Point = {
x: number,
y: number
}
function test(param: Point) {
console.log(param.x,param.y);
}

  1. 接口

interface Point {
x: number;
y: number;
}
function test(pt: Point) {
console.log(pt.x,pt.y);
}
test({x: 2,y: 10})

类型别名type和接口interface的区别是什么?

  • 拓展方法不同

//使用interface来拓展接口
interface Animal {
name: string;
}

interface Bear extends Animal {
hobby: string;
}

const bear: Bear = {
name: '熊',
hobby: '蜂蜜'
}

// 下面是使用type来拓展类型

type Animal = {
name: string
}

type Bear = Animal & {
hobby: string
}

const bear: Bear = {
name: "熊",
hobby: '吃蜂蜜'
}

  • 同名interface会合并不会覆盖,但是同名type是会报错的。

interface Bear {
name: string;
}

interface Bear {
age: number;
}

const bear: Bear = {
name: '熊',
age: 20
}

类型断言

类型断言的意义是告诉编译器这个变量是这种类型的,下面是两种定义方法,分别是as和尖括号语法。

// 类型断言
const myCanvas = document.getElementById('main_canvas') as HTMLCanvasElement;
const myCanvas2 = document.getElementById('main_canvas');

文字类型

文字类型可以指定文字的一些选项。

function test(s: string,align: 'left' | 'right' | 'center') {
console.log(s,align);
}
test('张三','left')

断言一定存在和可选参数

function test(name?: string | string[]) {
console.log(name!.toString());
}

枚举

枚举类型会自动进行递增。

enum Direction {
up = 1,
left,
right,
down
}
console.log(Direction.down); // 4

类型缩小

类型缩小就是将宽类型转换为窄类型的过程。

function test(padding: number | string,input: string) {
if (typeof padding === 'number') {
return new Array(padding + 1).join(" ") + input;
}
return padding + input;
}

in操作符

type Bird = {
fly: () => void;
}

type Bear = {
run: () => void;
}

function move(Animal: Bird | Bear) {
if ('fly' in Animal) {
return Animal.fly();
}
return Animal.run();
}

类型谓词

类型谓词是用于告诉某个情况下某个变量的类型。

type Fish = {
name: string;
swim: () => void;
}

type Bird = {
name: string;
fly: () => void;
}

function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim != undefined
}

function getSmallPet(): Fish | Bird {
let fish: Fish = {
name: 'sharkey',
swim: () => {}
};
let bird: Bird = {
name: 'sparrow',
fly: () => {}
}
return true ? bird : fish;
}

let pet = getSmallPet();

if (isFish(pet)) {
pet.swim();
} else {
pet.fly()
}

never类型和穷尽性检查

type Bird = {
kind: 'bird'
name: string;
}

type Animal = {
kind: 'animal'
name: string
}

function test(bird: Bird | Animal) {

switch (bird.kind) {
case 'bird':
return 1;
case 'animal':
return 666;
default:
const unknown: never = bird;
}
}

函数类型

function greeter(fn: (s: string) => void) {
fn('hello ts');
}

greeter((s: string) => {
console.log(s);
})

调用签名

调用签名主要是给函数绑定属性。

// 调用签名主要是给函数绑定属性
type DescribableFunction = {
description : string
(somArg: number): boolean
}

function doSomething(fn: DescribableFunction) {
console.log(fn.description + ' returned ' + fn(6)); // hello returned true
}

function fn1(n: number) {
console.log(n); // 6
return true;
}

fn1.description = 'hello'
doSomething(fn1);

构造签名

在调用签名的前面添加一个new就成为了一个构造签名了。

// 构造签名
class Ctor {
s: string
constructor(s: string) {
this.s = s;
}
}

type SomeConstructor = {
new (s: string): Ctor
}

function fn(ctor: SomeConstructor) {
return new ctor('hello')
}

const f = fn(Ctor)
console.log(f.s); // hello

泛型函数

泛型是不预先指定类型,而是在调用的时候才指定类型。

// 泛型

function firstElement(arr: Type[]): Type | undefined {
return arr[0];
}

const s = firstElement(['a','v','b']); // s是string类型

const n = firstElement([1,2,3]); // n是number类型

下面是一个多参数的泛型实例。

function map(arr: Input[],func: (arg: Input) => Output): Output[] {
return arr.map(func);
}

const parsed = map(['1','2','3'],(n) => parseInt(n)); // [1,2,3]

泛型函数的限制条件

泛型函数的限制条件是通过extends关键词实现的。

// 泛型函数的限制条件是通过extends关键词实现的,这里的extends并不是真的继承,而是一种限制。
function longest(a: Type,b: Type) {
if (a.length > b.length) {
return a;
} else {
return b;
}
}
const longerArray = longest([1,2],[2,3,4]);
const longerString = longest('felix','lu');
const notOk = longest(100,200) // 这里会报错

泛型函数指定类型参数

指定传给泛型的参数的类型。

function combine(arr1: Type[],arr2: Type[]): Type[] {
return arr1.concat(arr2);
}
const arr = combine(['a','b'],[1,2,3]);
console.log(arr); // ['a','b',1,2,3]

函数的可选参数

可选参数主要是通过冒号实现,表示该参数可以传递也可以不传递。

function f(n?: number) {
if (n) {
console.log('n is ',n);
} else {
console.log('n is undefined');
}
}
f()
f(11)

回调中的可选参数

表示回调函数中的某个参数是可选的。

function myForEach(arr: any[],callback: (arg: any, index?: number) => void) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i],i);
}
}
myForEach([1,2,3],(a) => console.log(a));
myForEach([1,2,3],(a,i) => console.log(a,i));

函数重载

// 函数重载
function makeDate(timestamp: number): Date;
function makeDate(m: number,d: number,y: number): Date;
// 函数重载的实现
function makeDate(mOrTimestamp: number, d?: number,y?: number): Date {
if (d != undefined && y != undefined) {
return new Date(y,mOrTimestamp,d)
} else {
return new Date(mOrTimestamp);
}
}

const d1 = makeDate(123456);
const d2 = makeDate(5,6,7);
const d3 = makeDate(5,9) // 此时会报错,因为传参要满足重载的任意一个,而不是重载的实现

参数展开运算符

function multiply(n: number,...m: number[]) {
return m.map(x => n * x);
}

const a = multiply(10,1,2,3,4);

参数的解构赋值

function sum({a,b,c}: {a: number,b: number,c: number}) {
console.log(a + b + c);
}

sum({a: 10,b: 20,c: 30});

只读属性

只读属性只能读不能修改,这是对常量而言的,如果是引用类型的话,只要地址不变,其内部的变量是可以进行修改的。

interface SomeType {
readonly prop: string;
}

function doSomething(obj: SomeType) {
console.log(obj.prop);
obj.prop = '666' // 这一行会报错。
}

交叉类型

被交叉类型定义的对象,需要同时满足交叉类型中的所有定义。

interface Colorful {
color: string
}

interface Circle {
radius: number
}

type ColorfulCircle = Colorful & Circle;

const cc: ColorfulCircle = {
color: 'red',
radius: 100,
}

在泛型约束中使用类型参数

function getProperty(obj: Type,key: Key) {
return obj[key];
}

let x = {
a: 1,
b: 2,
c: 3,
d: 4
}

getProperty(x,'a');
getProperty(x,'m'); // 报错

举报

相关推荐

0 条评论