TypeScript 简洁教程 TS

TypeScript 基础类型

数据类型 关键字 描述
任意类型 any 声明为 any 的变量可以赋予任意类型的值
数字类型 number 双精度 64 位浮点值。它可以用来表示整数和分数
字符串类型 string 使用单引号(')或双引号(")来表示字符串类型
布尔类型 boolean 表示逻辑值:true 和 false
数组类型 声明变量为数组
元组Tuple 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同
枚举 enum 枚举类型用于定义数值集合
void void 标识方法返回值的类型,表示该方法没有返回值
null null 表示对象值缺失
undefined undefined 用于初始化变量为一个未定义的值
never never 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。

************** 常用写法 **************

 //可以用 | 来支持多种类型
let arr1: (number | string)[] = [1, 'a', 3, 'b'];
let x: number | null | undefined;
let decLiteral: number = 6;    // 十进制
let arr:Array<number> =[1,2,3] === let arr:number[]=[1,2,3]
const inputValue = ref<(string | number)[]>([0, 0]);

type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };


interface SeletI {
  label: string;
  value: string | number;
}
const unitList1 = ref<SeletI[]>([]);
const unitList2 = ref([] as SeletI[]);

interface Cat {
    name?:string; //?表示可以不用
    run():void;
}
interface RunOptions { 
    program:string; 
    commandline:string[]|string|(()=>string); 
} 
interface IPerson { 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string 
} 
interface namelist { 
   [index:number]:string 
}
//接口中我们可以将数组的索引值和元素设置为不同类型,索引值可以是数字或字符串。
interface namelist { 
   [index:number]:string 
} 
// 类型一致,正确
var list2:namelist = ["Google","Runoob","Taobao"]
//数组
let arr: number[] = [1, 2];// 在元素类型后面加上[]
let arr: Array<number> = [1, 2];// 或者使用数组泛型
//元组
let x: [string, number];
x = ['Runoob', 1];    // 运行正常
//枚举
enum Color {Red, Green, Blue};
let c: Color = Color.Blue; // console.log(c);   输出 2

//void
function hello(): void {
    alert("Hello Runoob");
}

type 类型别名
// 改造前:
let arr1: (number | string)[] = [1, 'a', 3, 'b'];
let arr2: (number | string)[] = [2, 'c', 4, 'd'];
// 改造后:
type CustomArray =  (number | string)[];
let arr1: CustomArray  = [1, 'a', 3, 'b'];
let arr2: CustomArray  = [2, 'c', 4, 'd'];
const getValue = () => { return 0 }
enum List {
  A = getValue(), //A 的值是被计算出来的。某个属性的值是计算出来的,那么它后面一位的成员必须要初始化值
  B = 2,  // 此处必须要初始化值,不然编译不通过
  C
}
console.log(List.A) // 0
console.log(List.B) // 2
console.log(List.C) // 3

enum类型是对JavaScript标准数据类型的一个补充(使用枚举类型可以为一组数值赋予友好的名字 )

enum Language {  //枚举名称为大写的单数形式
    English,   //枚举中的键也为大写
    Spanish,
    Russian
}
console.log(Language);
//ts自动推导出来的Language如下
{
  '0': 'English',
  '1': 'Spanish',
  '2': 'Russian',
  English: 0,    
  Spanish: 1,    
  Russian: 2     
}

enum Color {Red, Green, Blue}
let c: Color = Color.Green;

//默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。 
//例如,我们将上面的例子改成从 1开始编号:
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;

//或者,全部都采用手动赋值:
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;

//枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 
//例如,我们知道数值为2,但是不确定它映射到Color里的哪个名字,我们可以查找相应的名字:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];  //console.log(colorName);  =>Green'因为上面代码里它的值是2

变量声明

//变量名称可含 数字、字母、 _ 、 $  不能包含其他特殊字符,包括空格。不能以数字开头。
//var [变量名] : [类型] = 值;
var uname:string = "Runoob";
//var [变量名] : [类型];//声明变量的类型,但没有初始值,变量值会设置为 undefined:
var uname:string;
//var [变量名] = 值;//声明变量并初始值,但不设置类型,该变量可以是任意类型:
var uname = "Runoob";

类型断言(Type Assertion)

  • 联合类型可以被断言为其中一个类型
  • 父类可断言为更加具体的子类
  • 任何类型都可以被断言为any
  • any可以被断言为任何类型
<类型>值   或者   值 as 类型
let value: any = 'hello world';
//类型断言
console.log((<string>value).length);
console.log((value as string).length);
//上面的类型断言的写法和下面类型断言的写法完全等价
// 类型断言
(value as string[]).push('test');
(<string[]>value).splice(0,1);
//只能访问联合属性中共有的属性和方法——name。
//如果在不确定类型的时候就想访问一个类型确定的属性和方法,就需要【断言】:
interface Cat {
    name:string;
    run():void;
}
interface Fish {
    name:string;
    swim():void;
}
function getName(animal:Cat|Fish):string{
    return animal.name;
}
//使用断言 可调用该类型的方法
function isFish(animal:Cat|Fish):boolean{
    return (typeof (animal as Fish).swim) === "function";
}

type 作为类型别名使用

//示例1   提取类型    
type PlusType = (x:number,y:number) => number;
function sum(x:number,y:number):number =>{   return x+y;  }
const sum2: PlusType  = sum;
//示例2   
type NameResolver = ( ) => string;
type NameOrResolver =  string | NameResolver;
function getName( n:NameOrResolver  ){
    if( typeof n === 'string' ){ 
      return n.length;
    }else{
       return  n().toString.length;
   }
}
function getLength( input : string | nmuber  ) :number{
  const str = input as string;//  将str断言为  string 
  if( str.length  ){ 
     return str.length 
  }else{  
    const num = input as number;
    return num.toSring().length;
  }
}

function getLength( input : string | nmuber  ) :number{
  if{(<string>input.length){
    return input.length;
  }else{
    return input.toString().length;
  }
}

class Car { 
    // 字段 
    engine:string; 
    // 构造函数 
    constructor(engine:string) {   this.engine = engine  }  
    // 方法 
    disp():void {  console.log("发动机为 :   "+this.engine)  } 
}

// 创建一个对象
var obj = new Car("XXSY1")
// 访问字段
console.log("读取发动机型号 :  "+obj.engine)  
// 访问方法
obj.disp()

解析为

var Car = /** @class */ (function () {
    // 构造函数 
    function Car(engine) {
        this.engine = engine;
    }
    // 方法 
    Car.prototype.disp = function () {
        console.log("发动机为 :   " + this.engine);
    };
    return Car;
}());

类继承

class Shape { 
   Area:number 
   constructor(a:number) {  this.Area = a  } 
} 
 
class Circle extends Shape { 
   disp():void {  console.log("圆的面积:  "+this.Area)   } 
}
  
var obj = new Circle(223); 
obj.disp()
//子类只能继承一个父类,TypeScript 不支持继承多个类,但支持多重继承,如下实例:
class Root {   str:string;  } 
 
class Child extends Root {} 
class Leaf extends Child {} // 多重继承,继承了 Child 和 Root 类
 
var obj = new Leaf(); 
obj.str ="hello" 
console.log(obj.str)

类继承方法重写

class PrinterClass { 
   doPrint():void {
      console.log("父类的 doPrint() 方法。") 
   } 
} 
 
class StringPrinter extends PrinterClass { 
   doPrint():void { 
      super.doPrint() // 调用父类的函数
      console.log("子类的 doPrint()方法。")
   } 
}

static

/*
静态属性, 是类对象的属性。即可以用类名直接访问
非静态属性, 是类的实例对象的属性。即通过实例化对象访问
*/
 
class Person {
  name1: string = 'A'
  static name2: string = 'B'
  constructor(a1:string, a2:string) {
    this.name1 = a1 //不会报错
    this.name2 = a2 //报错,this指向实例化对象,而namd2是静态属性,属于类对象的。
  }
}
 
console.log(Person.name2)
console.log(new Person().name1)

instanceof 运算符

class Person{ } 
var obj = new Person() 
var isPerson = obj instanceof Person; 
console.log("obj 对象是 Person 类实例化来的吗? " + isPerson);

访问控制修饰符

  • public(默认) : 公有,可以在任何地方被访问。
  • protected : 受保护,可以被其自身以及其子类访问。
  • private : 私有,只能被其定义所在的类访问。
class Encapsulate { 
   str1:string = "hello" 
   private str2:string = "world" 
}
var obj = new Encapsulate() 
console.log(obj.str1)     // 可访问 
console.log(obj.str2)   // 编译错误, str2 是私有的

类实现接口

interface ILoan { 
   interest:number 
} 
 
class AgriLoan implements ILoan { 
   interest:number 
   rebate:number 
   
   constructor(interest:number,rebate:number) { 
      this.interest = interest 
      this.rebate = rebate 
   } 
} 
 
var obj = new AgriLoan(10,1) 
console.log("利润为 : "+obj.interest+",抽成为 : "+obj.rebate )

泛型

泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候在指定类型限制的一种特性。

function test <T> (arg:T):T{
  console.log(arg);
  return arg;
}
test<number>(111);// 返回值是number类型的 111
test<string | boolean>('hahaha')//返回值是string类型的 hahaha
test<string | boolean>(true);//返回值是布尔类型的 true

//接口中使用泛型
// 注意,这里写法是定义的方法哦
interface Search {
  <T,Y>(name:T,age:Y):T
}

let fn:Search = function <T, Y>(name: T, id:Y):T {
  console.log(name, id)
  return name;
}
fn('li',11);//编译器会自动识别传入的参数,将传入的参数的类型认为是泛型指定的类型

//类中使用泛型
class Animal<T> {
 name:T;
 constructor(name: T){
  this.name = name;
 }
 action<T>(say:T) {
   console.log(say)
 }
}
let cat = new Animal('cat');
cat.action('mimi')

使用接口约束泛型

interface Person {
  name:string;
  age:number;
}
function student<T extends Person>(arg:T):T {
  return arg;
}

student({name:'lili'});//类型 "{ name: string; }" 中缺少属性 "age",但类型 "Person" 中需要该属性
student({ name: "lili" , age:'11'});//不能将类型“string”分配给类型“number”
student({ name: "lili" , age:11});

数组泛型

let arr:Array<number> =[1,2,3] === let arr:number[]=[1,2,3]

泛型工具类型

partial<T>的作用就是将某个类型中的属性全部变为可选项?
Record<K extends keyof any, T>的作用是将K中所有的属性转换为T类型
Pick<T, K extends keyof T>的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型
Exclude<T,U>的作用是将某个类型中属于另一个类型的属性移除掉
returnType<T>的作用是用于获取函数T的返回类型

命名空间

namespace SomeNameSpaceName { 
   export interface ISomeInterfaceName {      }  
   export class SomeClassName {      }  
}

如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠 /// 引用它,语法格式如下:

//IShape.ts 文件代码:
namespace Drawing { 
    export interface IShape { 
        draw(); 
    }
}
//Circle.ts 文件代码:
/// <reference path = "IShape.ts" /> 
namespace Drawing { 
    export class Circle implements IShape { 
        public draw() { 
            console.log("Circle is drawn"); 
        }  
    }
}
//Triangle.ts 文件代码:
/// <reference path = "IShape.ts" /> 
namespace Drawing { 
    export class Triangle implements IShape { 
        public draw() { 
            console.log("Triangle is drawn"); 
        } 
    } 
}
//TestShape.ts 文件代码:
/// <reference path = "IShape.ts" />   
/// <reference path = "Circle.ts" /> 
/// <reference path = "Triangle.ts" />  
function drawAllShapes(shape:Drawing.IShape) { 
    shape.draw(); 
} 
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());

模块

//命名空间引入
/// <reference path = "IShape.ts" /> 
export interface IShape { 
   draw(); 
}

引入模块

import shape = require("./IShape"); 
export class Circle implements shape.IShape { 
   public draw() { 
      console.log("Cirlce is drawn (external module)"); 
   } 
}

菜鸟教程
https://www.runoob.com/typescript/ts-module.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容