分享好友 编程语言首页 频道列表

Typescript学习笔记 TYPESCRIPT

typescript文章/教程  2023-02-09 10:200

TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript。

 

安装 TypeScript

命令行工具安装:

npm install -g typescript

编译一个 TypeScript 文件:

tsc hello.ts

 

 

原始数据类型/ 任意值

为每一个变量提前申明该类型,则该变量取值只能为申明的类型,否则报错

如果一个变量可以任意取值,可以通过any 申明该变量为任意值

原始数据类型包括:布尔值(boolean)、数值(number)、字符串(string)、nullundefined、Symbol(ES6)共六种

申明为number类型的变量,后面可以取值类型为 number  、nullundefined,会默认进行隐式转换

 

例子:

let isDone: boolean = false;        //申明该值为 boolean 类型

let decLiteral: number = 6;

let notANumber: number = NaN;       // 进行隐式转换

let infinityNumber: number = Infinity;  // 进行隐式转换

let num: number = undefined;   // 进行隐式转换

let myName: string = 'Xcat Liu';

let u: undefined = undefined;

let n: null = null;
 
let anytest: any = 123;   //申明该值为任意类型
anytest = true;
anytest = '任意值'

//  内置对象类型申明

let b: Boolean = new Boolean(1);    // 申明为 Boolean 类型

let e: Error = new Error('Error occurred');    //申明为错误类型

let d: Date = new Date();   // 申明为 时间类型

let r: RegExp = /[a-z]/;    //申明为正则类型

let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
document.addEventListener('click', function(e: MouseEvent) { // Do something });
 

 

 

 

提前申明变量的类型也可以用在functiuon函数传参,用于规定该参数的类型

在 TypeScirpt 中,可以用 void 表示没有任何返回值的函数

例子:
function sayHello(person: string) {     // 在函数出入的参数后面申明类型
    return 'Hello, ' + person;
}


function test(): void {     //void 表示该函数没有返回值
  alert('Hello Wrold');
}

 

 

联合类型

联合类型表示取值可以为多种类型中的一种。使用 | 分隔每个类型。

let test: string | number;    //申明 test变量的类型为string 或者 number其中一种
test = 'seven';     //test的取值可以为其中一种类型
test = 7;

 

当不确定一个使用了联合类型的变量是哪种类型时,只能访问此联合类型的所有类型里共有的属性或方法

function getString(something: string | number) {     //申明传入的参数为string或者number类型
  return something.toString();        // 只能调用string和number共有的方法
}

 

错误例子:

function getLength(something: string | number) {
  return something.length;       // number类型不存在length
}

 

 

对象的类型——接口 (interfaces)

即提前定义一个对象的类型规则,用于申明一个对象时进行类型匹配

interface Person {     //使用interface定义一个对象的类型,取名Person    首字母一般大写
  name: string;        //申明该对象每个值的取值类型
  age: number;
}

let xcatliu: Person = {     // 申明一个xcatliu对象,使用Person规则进行匹配验证
  name: 'Xcat Liu',
  age: 25,
};

 

 

 使用Interfaces来定义对象的类型,定义了类型的对象,定义的变量不允许比类型少,也不能多,结构必须一模一样

错误例子:

 

interface Person {
  name: string;
  age: number;
}

let xcatliu: Person = {    //不能比定义的Person类型的变量少
  name: 'Xcat Liu',
};

let xcatliu: Person = {
  name: 'Xcat Liu',
  age: 25,
  website: 'http://xcatliu.com',   /不能比定义的Person类型的变量多
};

 

  

如果我们希望不要完全匹配一个 类型,可以使用可选属性: 可选属性的含义是该属性可以不存在。使用 ?      但是仍然不允许添加未定义的属性

 

interface Person {
  name: string;
  age?: number;      //在属性后面加上? 表示该属性可有可无
}

let xcatliu: Person = {
  name: 'Xcat Liu',
};

 

 

有时候我们希望一个接口允许有任意的属性,即可以任意添加属性个数,使用 任意属性  [propName: string]

一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性    任意属性的取值类型为 any ,否则会跟可选属性冲突

 

interface Person {
  name: string;
  [propName: string]: any;     // 表示可以任意添加属性个数  ,添加的属性类型为 any
}

let xcatliu: Person = {
  name: 'Xcat Liu',
  website: 'http://xcatliu.com',   //任意添加的属性
  websit2: 'http://xcatliu.com',    //任意添加的属性
};

 

 对象中的一些字段只能在创建的时候被赋值,那么可以用 readonly 定义只读属性,在刚刚创建对象的时候赋值,后面不允许改变该属性值。也不能在创建的时候未定义值

readonly 定义在属性的前面,用空格区分

interface Person {
  readonly id: number;   //使用 readonly 定义只读属性
  name: string;
}

let xcatliu: Person = {
  id: 89757,
  name: 'Xcat Liu',
};

xcatliu.id = 9527;    //报错  不能改变该属性值

 

 

 

数组的类型

数组的类型用于定义申明一个数组时的格式,申明格式类型的数组不能使用其他类型的方法

对象中的接口定义类型方法也同样适用于数组

 

let testArr: number[] = [1,2,5,4,8]     //申明一个数组的类型为 number

let fibonacci: string[] = ["1","2"];    //申明一个数组的类型为 string

let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }];   // 申明一个数组的类型为任意类型

let fibona: Array<number> = [ 1, 2, 3, 5];   //也可以使用数组泛型Array<elemType> 来表示数组

interface NumberArray {      //使用接口定义一个数组的类型,表示该数组取值必须为 string 类型
  [index: number]: string;
}
let fi: NumberArray = ["a","1"];

interface NumberArr {        //使用接口定义一个数组的类型,表示该数组取值必须为 number 类型
  [index: number]: number;
}
let fi2: NumberArr = [1, 1, 2, 3, 5];

 

类数组不是数组类型,比如 arguments  ,不能使用数组的类型定义方式

 常见的类数组都有自己的接口定义,如 IArguments, NodeList, HTMLCollection 等

 

function sum() {
  let args: IArguments = arguments;    // arguments是类数组类型,使用 IArguments
}

 

 

函数的类型

定义函数的类型,对函数传入的参数和返回值做一定的限制

输入多余的(或者少于要求的)参数,是不被允许的,

function sum(x: number, y: number): number {     //申明一个函数sum  限制其传入的参数为 number类型,返回的参数为 number类型
  return x + y;
}

sum(1, 2);

 

 

如果是一个函数表达式,,那么需要对左右两边进行类型的限制

//申明了一个 mySum函数,申明其类型为number
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
  return x + y;
};

 

 函数的类型定义同样可以使用对象的接口

 

interface SearchFunc {      //使用接口申明一个类型,名称为 SearchFunc
  (source: string, subString: string): boolean;     //申明该函数的传入值都为 string   返回值为 boolean
}

let mySearch: SearchFunc;     //申明一个函数,使用 SearchFunc 类型规则
mySearch = function(source: string, subString: string) {
  return source.search(subString) !== -1;
}

 

 

函数的类型也可以定义可选的传入参数, 在参数后面使用 ?

可选参数必须接在必需参数后面

function buildName(firstName: string, lastName?: string) {    // lastName 为可选参数
  if (lastName) {
    return firstName + ' ' + lastName;
  } else {
    return firstName;
  }
}
let xcatliu = buildName('Xcat', 'Liu');
let xcat = buildName('Xcat');

 

 

TypeScript 会将添加了默认值的参数识别为可选参数     使用默认值的可选参数不限制位置

 

function buildName(firstName: string, lastName: string = 'Liu') {     // lastName 为可选参数
  return firstName + ' ' + lastName;
}
let xcatliu = buildName('Xcat', 'Liu');
let xcat = buildName('Xcat');

function reverse(x: number | string): number | string {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''));
  } else if (typeof x === 'string') {
    return x.split('').reverse().join('');
  }
}

 

 

ES6 中,可以使用 ...rest 的方式获取函数中的剩余参数,items 是一个数组。可以用数组的类型来定义它:

function push(array: any[], ...items: any[]) {     //...items表示剩余参数,是一个数组,可以申明为任意类型的数组
  items.forEach(function(item) {
    array.push(item);
  });
}

let a =  [];
push(a, 1, 2, 3);

 

 

 

类型断言   <类型>值     值 as 类型

类型断言可以用来绕过编译器的类型推断,手动指定一个值的类型

TypeScript在使用联合类型时,默认不能引用不确定类型的方法,只能引用共有的方法,某些时刻,我们需要使用类型断言,即申明此时的属性为某个类型

类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的   断言的类型必须是联合类型中的某一个

function getLength(something: string | number): number {
  if ((<string>something).length) {   // 默认不能使用 length属性,使用类型断言 <string>   将此时的something申明为 string类型
    return (<string>something).length;
  } else {
    return something.toString().length;
  }
}

 

 

类型别名

类型别名用来给一个类型起个新名字。使用 type

 

type Name = string;        // 使用 type 将string类型起名为 Name
type NameResolver = () => string;      //另一种写法
type NameOrResolver = Name | NameResolver;     //使用该别名
function getName(n: NameOrResolver): Name {
  if (typeof n === 'string') {
    return n;
  }
  else {
    return n();   
  }
}

 

 

字符串字面量类型

字符串字面量类型用来约束取值只能是某几个字符串中的一个。同样使用 type

type test = 'click'|'scroll'|'mousemove'       // 使用 type 规定test变量为三个值其中一个
function handleEvent(ele: Element, event: test) {   //使用test类型,传入的值为规定值的其中一个
  // do something
}
handleEvent(document.getElementById('hello'), 'scroll');  

 

 

 

元组

数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。

简单理解,在数组类型中,要么规定数组中的每个值都为某种类型,要么都为任意类型。使用元组,可以依次给每个值指定类型

let xcatliu: [string, number] = ['Xcat Liu', 25];

 

 

我们也可以在定义数组类型后,通过索引依次赋值,也可以只赋值其中一项

当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项。

let xcatliu: [string, number];    //先定义每个值的类型
xcatliu[0] = 'Xcat Liu';     // 通过索引赋值
xcatliu[1] = 25;

xcatliu[0].slice(1);     //可以通过索引调用对应类型的方法
xcatliu[1].toFixed(2);


let xcatliu: [string, number] = ['Xcat Liu'];   //报错,需要全部赋值

 

 

当我们去访问数组未定义的下标或者对其进行赋值时,它的类型为已存在元素的类型组成的联合类型,能够调用的方法为联合类型共有的方法

let xcatliu: [string, number];

xcatliu = ['Xcat Liu', 25, 'http://xcatliu.com/'];    // 第三个值的类型为 string|number

xcatliu.push(true);     // 报错   true 是 boolean 类型

console.log(xcatliu[2].slice(1));   // 报错   slice不是 string|number 共有的方法

 

 

 

TypeScript 中类的用法    public privateprotected

  • public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
  • private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
  • protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的

 

 

class Animal {
  public name;           //表示公共的,在任何地方都可以被访问
  private age;          //表示私有的,不允许被访问,也不能继承
  protected height;     //表示受保护的,只能通过继承访问
  public constructor(name) {
    this.name = name;
  }
}

var a = new Animal('Jack');
console.log(a.name);        
console.log(a.age);      //报错,不允许被访问
console.log(a.height);  // 报错,只能通过继承访问

 

 

abstract 用于定义抽象类和其中的抽象方法 

 抽象类是不允许被实例化的,即不能通过new去实例化,只能被继承

抽象类中的抽象方法必须被子类实现,即使用abstract 定义为抽象方法,那么必须在子类实现

 

abstract class Animal {
  public name;
  public constructor(name) {
    this.name = name;
  }
  public abstract sayHi();     //抽象方法
}

class Cat extends Animal {
  public sayHi() {     // 继承 Animal类后实现定义的抽象方法
    console.log(`Meow, My name is ${this.name}`);    
  }
}

let cat = new Cat('Tom');

 

 

 

类实现接口  implements

不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。

 

interface Alarm {    //使用 interface 定义了一个接口,里面是一个 alert 方法
  alert();
}

class Door {
}
 
class SecurityDoor extends Door implements Alarm {    // SecurityDoor继承了 Door类并且引用了 Alarm 接口的方法
  alert() {
    console.log('SecurityDoor alert');
  }
}

class Car implements Alarm {      // Car类 引用了Alarm 接口的方法
  alert() {
    console.log('Car alert');
  }
}

 

 

一个类可以同时引用多个接口

interface Alarm {
  alert();
}

interface Light {
  lightOn();
  lightOff();
}

class Car implements Alarm, Light {
  alert() {
    console.log('Car alert');
  }
  lightOn() {
    console.log('Car light on');
  }
  lightOff() {
    console.log('Car light off');
  }
}

 

 

 接口与接口之间也可以相互继承:

interface Alarm {
  alert();
}

interface LightableAlarm extends Alarm {
  lightOn();
  lightOff();
}

 

 

 

 

 

查看更多关于【typescript文章/教程】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint
electron教程(一): electron的安装和项目的创建electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google JavaScript Style Guide代码规范electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLintelectron

0评论2023-03-08610

使用TypeScript,AngularJs和Web API构建基本的CRUD Web 应用
原文地址:using typescript with angularjs and web api 版权归其作者所有.在这篇文章中我将向大家展示如何使用TypeScript,Angular Js 和Asp.net Web API 来构建一个基本的实现CRUD功能的Web应用程序. Typescript提供了一系列的功能来方便程序员构造和组织更

0评论2023-02-10391

Typescript 中类的继承
Typescript中类的定义与继承与后端开发语言java/C#等非常像,实现起来非常方便,而且代码便于阅读。用Typescript写较大项目时是非常有优势的。/** * BaseClass */class BaseClass {constructor(name:string,age:number) {this.name=name;this.age=age;}name:s

0评论2023-02-09350

TypeScript实现设计模式——工厂模式
上回用typescript实现了单例模式,这回来实现工厂模式。工厂模式又分为简单工厂模式、工厂方法模式以及抽象工厂模式。简单工厂模式简单工厂模式通常在业务比较简单的情况下使用,它有三个部分组成:工厂类、抽象产品类、具体产品类。抽象产品类abstract class

0评论2023-02-09907

使用Visual Studio Code和typescript 开发调试React Native项目
关于React Native的详细介绍我就不叙述了,他是使用js构建原生app的开发框架。一次变编码多平台运行,非常强大。但是个人不喜欢js的过于灵活(弱类型)的语法。强大的强类型语言Typescript(简称TS)是我的首选,他可以编译成JavaScript,编译成的JavaScript代

0评论2023-02-09391

TypeScript的安装、使用及配置
JS是一种弱类型语言,对于代码的维护和重构是非常困难的。TypeScript是一个编译到纯JS的有类型定义的JS超集,可以极大的提升代码的健壮性。使用TS后,能够方便的查看函数定义、默认参数及类型、变量结构体等,同时对于IDE的参数类型提示也是非常友好的。优点

0评论2023-02-09713

vue-type-check: Vue 模板中的 Typescript 类型检查
越来越多人开始尝试使用 Typescript 编写他们的 vue 项目,vue 本身也在不断加强对 Typescript 的支持(官方提供 vue-class-component 库、使用 Typescript 编写 Vue 3.0 等),但是对于组件中模板部分的类型检查仍然有很大的局限性。为此我们开源了一个易

0评论2023-02-09756

JavaScript面向对象轻松入门之抽象(demo by ES5、ES6、TypeScript)
抽象的概念  狭义的抽象,也就是代码里的抽象,就是把一些相关联的业务逻辑分离成属性和方法(行为),这些属性和方法就可以构成一个对象。  这种抽象是为了把难以理解的代码归纳成与现实世界关联的概念,比如小狗这样一个对象:属性可以归纳出“毛色”、

0评论2023-02-09777

Angular2+typescript+webpack2(支持aot, tree shaking, lazy loading)
Angular2官方推荐的应该是使用systemjs加载, 但是当我使用到它的tree shaking的时候,发现如果使用systemjs+rollup,只能打包成一个文件,然后lazy loading就没法搞了。因此我使用了webpack2,webpack2自带tree shaking,只要将tsconfig中的module设置成es201

0评论2023-02-09811

typescript结合three.js
import * as THREE from "three";// https://github.com/pinqy520/three-typescript-starter/blob/master/src/index.tsclass Game{private _scene: THREE.Scene;//private _canvas: HTMLCanvasElement;private _camera: THREE.PerspectiveCamera;private _ren

0评论2023-02-09748

更多推荐