前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TypeScript 基础教程

TypeScript 基础教程

原创
作者头像
路过的那只狗
发布2020-11-14 16:05:38
1K0
发布2020-11-14 16:05:38
举报
文章被收录于专栏:随便写写

请查看 附件,ppt 以及示例代码。title 处 #数字 表示对应示例代码片段。

为什么学习TS


  • 因为大家都在用,React、Vue、Angular、Antd、Element-UI、Mobx、Redux…
  • 因为大家都在学,既是一个前端的趋势也是提升扩展个人技术的不错方法。

为什么需要使用TS


通过引入强类型系统,补充JS的短板。原生JS类型的灵活性导致在实际环境中可能会出现各种不确定的bug。通过使用TS,我们可以在开发阶段既预测这些可能由类型转换导致的错误,从而提前规避bug,开发出更健全的程序。

TypeScript 的安装与基础使用


安装:

npm i typescript -g

使用:

  • tsc { ptah }/{ fileName },可以直接将 .ts 文件 编译为 .js文件
  • tsc -- init , ⽣成项⽬配置:tsconfig.json,通过配置文件可以设置 .ts 文件

TypeScript 的基本类型


boolean:

同 js 布尔值类型,true / false。

string:

同 js 字符串类型,使⽤单引号、双引号、模版字符串。

number:

数字类型,⼆进制、⼋进制、⼗进制、⼗六进制。

null、undefined:

null,undefined :同js值类型,默认是所有类型的⼦类型所以,可以给任意类型的变量赋值nullundefined

any:

定义:任意值类型,可以赋值任意值类型,注意这里与 null,undefined有区别,null,undefined 是所有类型的子类型,表明它是所有类型的子集,而 any 类型则是:“所有类型都是 any 类型的子集”。

代码语言:txt
复制
let baz: string = "baz";
let bar: number = 1;
let qux: boolean = false;
let foo: any = 1;
let norf: null = null;
qux = null;
qux = undefined;
foo = "foo"

void:

定义:无返回值的值类型,可以理解为 undefined 类型的子类型。作为一个类型,它也可以当作函数参数类型限定

代码语言:txt
复制
button.onclick = () => void doSomething();

function doSomething(callback: () => void) {
  let foo = callback();
}

never:

定义:表示永远不存在的值类型,比如:程序运行报错,程序陷入了无线循环。

代码语言:txt
复制
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
  throw new Error(message);
}

// 推断的返回值类型为never
function fail() {
  return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
  while (true) {
  }
}

Symbol 类型 当前并无支持

type 类型别名


定义:给⼀个类型起⼀个新的名字,使⽤ type 作为声明关键字。常用于复合类型数据变量的类型声明。 对象类型约定使用大写字母开头type 声明的类型,里面包含的属性必须刚好全部满足,不能多也不能少,否则编译将报错,可选属性除外。

代码语言:txt
复制
type Name = string;
const myName: Name = "foo";

type Age = number;
const myAge: Age = 18;

// 声明复杂类型
// 类型声明里的属性必须存在,可选属性声明前使用: "?"
type User = {
  name: string;
  sex: string;
  age: number;
  adult: boolean;
  isProgramer?: boolean; // isProgramer是可选属性
};

let foo: User = {
  name: 'foo',
  sex: "man",
  age: 18,
  adult: true,
  isProgramer: true
};
/*
// Error 
let bar: User = {
  weight: 100
}
*/

interface 接口


定义: 对⾏为或是事物的抽象,进⾏描述。具体⾏为由类(function/class)去实现 (implement)。

举例:招募一个鸭子合唱团,招募要求是会:呱呱呱的叫声。这时候如果有一只公鸡,并且它的叫声是 “呱呱呱” 那么它便可以被招募,可以成为鸭子合唱团中的一员,或者说可以被当作鸭子。所以 interface 只是对某一类事物进行描述,如果一个具体事物拥有这样的属性, 那么它就是这一类型。 同类型别名 type 属性声明,可以使用 ?声明可选属性。

代码语言:txt
复制
// 定义接口
interface Person {
  sex: string;
  age?: number;
}
// 数据直接赋值
let bar: Person = {
  sex: "man",
  age: 18,
}
// 对接口进行实现
class Chinese implements Person{
  name: string;
}
// 构造调用与赋值
const wilde = new Chinese();
wilde.name = "mouguiding";

注意:类型别名 type 与接口interface 都可以声明复合类型类型的变量, 他们同样可以使用 readonly 来声明只读类型的属性, 使用 ? 来声明可选属性,但是他们存在一定区别。

type 与 interface 的异同

  • 都可以描述一个对象或者函数
  • 都允许扩展
  • type 可以声明基础类型别名,联合类型,元组等。 interface不可以
  • interface 可以声明合并。
代码语言:txt
复制
{
  // 描述一个对象或是函数
  {
    interface User {
      name: string
      age: number
    }
    interface SetUser {
      (name: string, age: number): void;
    }
  }
  {
    type User = {
      name: string
      age: number
    };
    type SetUser = (name: string, age: number)=> void;
  }

  // 扩展
  {
    interface Name { 
      name: string; 
    }
    interface User extends Name { 
      age: number; 
    }
  }
  {
    type Name = { 
      name: string; 
    }
    type User = Name & { age: number  };    
  }
  {
    type Name = { 
      name: string; 
    }
    interface User extends Name { 
      age: number;
    }
  }
  {
    interface Name { 
      name: string; 
    }
    type User = Name & { 
      age: number;
    }
  }
  // 不同点
  // type可以 interface 不行的
  {
    // 基本类型别名
    type Name = string
    // 联合类型
    interface Dog {
        wang();
    }
    interface Cat {
        miao();
    }
    type Pet = Dog | Cat
    // 具体定义数组每个位置的类型
    type PetList = [Dog, Pet]
    // 当你想获取一个变量的类型时,使用 typeof
    let div = document.createElement('div');
    type B = typeof div
  } 
  // interface 可以  type 不可以的, 声明属性合并
  {
    interface Person {
      name: string
      age: number
    }
    interface Person {
      sex: string
    }
    interface Programer extends Person{
      skill: string;
    }
  }

}

Typescript 中数组的类型声明


类型声明使用 Type:[] 或者 Array<Type>,尖括号<> 用于类型约束

代码语言:txt
复制
// 声明元素类型为字符串的数组
let foo: string[] = [ “foo”, “bar”, “baz” ]

// 声明元素类型为字符串的数组
let bar: Array<string> = [ “foo”, “bar”, “baz” ]
// bar.push(5) // error

// 声明元素类型为字符串或者数字的数组
let baz: Array<string|number> = [ “foo”, 100 ]
baz.push(10);

Typescript 中对象的类型声明


代码语言:txt
复制
// 使用 类型别名声明类型
type User = {
  name: string;
  sex: string;
  age: number;
  adult: boolean;
  isProgramer?: boolean;
};
let foo: User = {
  name: 'foo',
  sex: "man",
  age: 18,
  adult: true,
  isProgramer: true,
};

// 使用接口 interface 声明类型
interface Person {
  readonly name: string;
  sex?: string;
  age?: number;
}
let bar: Person = {
  name: 'bar',
  sex: "man",
  age: 18,
}

Typescript 中函数的类型声明


函数声明主要涉及到函数参数类型声明以及函数返回值类型限定。

代码语言:txt
复制
let fun71: any;
fun71 = function(): void {
  console.log("I'm fun71");
}
function fun72(): any {
  return "any";
};

let fun73: Function;
fun73 = function(): void{
  console.log("I'm fun73");
};

let fun74: (str: string) => string;
fun74 = function(name) {
  return `I'm ${name}`;
};

type Fun75 = (str: string) => string;
const fun75: Fun75 = function(name) {
  return `I'm ${name}`;
};

interface Fun76{
  (x: number, y: number): number;
}
const fun76: Fun76 = (x, y) => {
  return x + y;
}

interface Fun77{
  (x: number, y?: number): number;
}
const fun77: Fun77 = (x, y) => {
  if (y) return x + y;
  return x; 
}

函数重载

函数重载允许用相同的名字与不同的参数来创造多个函数

  1. 先提供没有实现的函数定义列表
  2. 必须提供所有函数组合的实现
代码语言:txt
复制
function sum(x: number, y: number): number;
function sum(x: number, y: number, z: number): number

function sum(x: number, y: number, z?: number): number {
	if (typeof z === 'undefined') {
		return x + y;
	} else {
		return x + y + z;
	}
}
let n = sum(1, 2, 3);
console.log(n);
n = sum(1, 2);
console.log(n);

Typescript 高级类型


union 联合类型:

定义:该类型的取值可以是多种类型的⼀种, 使用竖线对多种类型进行联合。每个类型可以是单一类型或复合类型

代码语言:txt
复制
type RTX = number|string|null;
let foo: RTX = "bar";
foo = 123;
foo = null;
foo = undefined;

interface Dog {
  wang();
}
interface Cat {
  miao();
}
type Pet = Dog | Cat

Tuple 元组:

定义:数组合并了相同类型的对象,元组则是合并了不同类型的对象,并且指定位置。注意是指定位置,与数组声明不同的是,数字只是限定了类型,不限定长度与位置

代码语言:txt
复制
interface Dog {
  wang();
}
interface Cat {
  miao();
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型, 值类型位置不能变换。
type PetList = [Dog, Pet, Cat];
let dog: Dog = {
  wang: () => {}
}
let cat: Cat = {
  miao: () => {}
}
let petlist: PetList = [dog, dog, cat]

enum 枚举:

定义: 类型⽤于取值被限定在⼀定范围内的场景 ,⽐如⼀周只能有七天,颜⾊限定为红绿蓝等,值为序号,可⾃定义值。重点:值为序号,相当于数组的下标,而不是本身。

代码语言:txt
复制
// 它的值是数字序号,从 0 开始
// 代码可读性强
// 可能会常用于下拉框等应用
enum DaysOfTheWeek {
	SUN = 100, MON, TUE, WED, THU, FRI, SAT
}
let day: DaysOfTheWeek;
	day = DaysOfTheWeek.MON;
if (101 === day) {
	console.log("Got to go to work");
} else {
	console.log("Don't work");
}

字面量类型:

定义:字面量类型使用竖线直接分割值(PS:联合类型是使用竖线联合类型,这里是值),此变量的值只能从分隔的值其中一个,使用 类型别名 type 搭配 |声明。

代码语言:txt
复制
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
    // do something
}
// handleEvent(document.getElementById('hello'), 'scroll');  // 没问题
// handleEvent(document.getElementById('world'), 'dbclick'); // 报错,event 不能为 'dbclick'

Generics 泛型:

定义:是指在定义函数、接⼝或类的时候,不预先指定具体的类型,⽽在使⽤的时候再指定类型的⼀种特性。泛型不是 any

代码语言:txt
复制
// 实现一个方法,输入两个参数,第一个是数字 N,
// 第二个是一个简单类型数据,返回重复 N 次的指定类型数组
type CreateArrayType<T> = (x:number, y:T) => T[];
const createArray2:CreateArrayType<number> = (x, y) => {
  let result = [];
  for(let i=0; i<x; i++){
    result[i] = y;
  }
  return result;
}
createArray2(2, 2);

其他部分


类型约束:

类型约束,常见的为使用<>进行限定。

如数组声明中:

代码语言:txt
复制
let arr53: Array<string|number|boolean> = [true, 100, "bar"];

其次如当我们需要返回一个变量的长度时,首先这个变量需要一个长度的属性那么,声明变量类型时它应该拥有长度属性:

代码语言:txt
复制
// 声明 LengthType 类型,必须包含 length 属性
interface LengthType {
  length: number;
}

// T 继承自 LengthType 类型,也就表明它必须具有 length 属性
function get<T extends LengthType>(arg: T): number {
  return arg.length;
}

特别是在使用泛型时,因为类型的不确定性导致程序可能会运行报错,善用类型约束可以提前处理这些问题。

类型断言:

可以理解为类型强制转换,就是把一个变量指定为另一个类型。

代码语言:txt
复制
let foo: any;
let bar = <string>foo; // 现在 bar 的类型是 'string'

interface Foo {
  bar: number;
  bas: string;
}
const foo = {} as Foo;

// 双重类型断言
function handler(event: Event) {
  const element = (event as any) as HTMLElement; 
}

类型推论:

定义:TypeScript 会通过变量或返回值等赋值时推导出这个值的类型,如果在随后的代码中又进行了不同类型的值赋值,那么编译会报错:

代码语言:txt
复制
let foo = 'hello,world';
foo = 9999;
Type '9999' is not assignable to type 'string'.

如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查

代码语言:txt
复制
let foo;
foo = 'bar';
foo = 18;     //ok

特别对于联合类型时,类型推论会限制到只能访问联合类型中类型的共有属性。否则将报错。

代码语言:txt
复制
//正确,因为num都有toString方法
function test(num: string | number) {
  return obj .toString()
}
let num = 'server';
console.log(test(num))

//编译错误,number类型的num 不存在length属性
function test(num: string | number) {
  return num.length;
}
let num = 'server';
console.log(test(num))

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么学习TS
  • 为什么需要使用TS
  • TypeScript 的安装与基础使用
  • TypeScript 的基本类型
  • type 类型别名
  • interface 接口
    • type 与 interface 的异同
    • Typescript 中数组的类型声明
    • Typescript 中对象的类型声明
    • Typescript 中函数的类型声明
    • Typescript 高级类型
    • 其他部分
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档