文档章节

TypeScript学习笔记

fzyz_sb
 fzyz_sb
发布于 2017/08/28 20:25
字数 1822
阅读 168
收藏 0
点赞 0
评论 0

基础类型

以冒号开头后跟类型名称.

let isDone: boolean = false;
let num: number = 6;
let color: string = "blue";
let list: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];

集合是特殊的数组类型, 它允许不同类型的元素存在于同一个数组中:

let x: [string, number]
x = ["hello", 10]
x[3] = "world"
// [ 'hello', 10, , 'world' ]
console.log(x)

枚举类型:

enum Color {Red, Green, Blue}
let c: Color = Color.Green
// 1
console.log(c)

通用类型any:

let notSure: any = 4
notSure = 'hello'

let list: any[] = [1, true, 'free']
list[1] = 100

void: 在声明函数则代表无返回值; 声明变量则代表只能赋值undefined, null

function warnUser(): void {
    //
}

let unusable: void = undefined;

null和undefined: 一般很少使用, 直接用any即可. 如果非要声明变量为undefined, null, 也可直接使用void:

let u: undefined = undefined;
let n: null = null;

类型转换:

let someValue: any = 'this is a string'
let strLength: number = (<string>someValue).length
let strLength1: number = (someValue as string).length

 

变量声明

var不推荐使用, 因为ES5中没有块级作用域:

// 10 10 10 10 10 10 10 10 10 10
for (var i = 0; i < 10; i++) {
    setTimeout(() => console.log(i), 100 * i)
}

一般遇到这种情况, 只能修改成如下代码:

// 0 1 2 3 4 5 6 7 8 9
for (var i = 0; i < 10; i++) {
    ((i) => {
        setTimeout(() => console.log(i), 100 * i)
    })(i)
}

let具有块级作用域, 所以用let来替换var.

let语法可用于数组/对象的解析:

let [first, second] = [1, 2]
// 1 2
console.log(first, second)
let [first1, ...rest] = [1, 2, 3, 4]
// 1 [2, 3, 4]
console.log(first1, rest)
let o = {
    a: 'foo',
    b: 12,
    c: 'bar'
}
let {a, b} = o
// foo 12
console.log(a, b)
let {c, ...passthrough} = o
// bar {a: 'foo', b: 12}
console.log(c, passthrough)

也可以指定别名:

let {a: newName1, b: newName2} = o
// equal to
let newName1 = o.a
let newName2 = o.b

也可以指定默认值:

let {a, b = 1001} = o

const专门用于定义常量.

ES6中新引入的"..."用于解构数组或变量:

let first: number[] = [1, 2]
let second: number[] = [3, 4]
let both = [0, ...first, ...second, 5]
// [0, 1, 2, 3, 4, 5]
console.log(both)

let defaults = {a: 1, b: 2}
let search = {...defaults, c: 3}
// { a: 1, b: 2, c: 3 }
console.log(search)

 

接口

编写一个函数, 指定参数类型, 之前可以这么写:

function func(obj: {label: string}) {
    console.log(obj.label)
}

let obj = {size: 10, label: 'object'}
func(obj)

而使用接口, 代码可修改如下:

interface Obj {
    label: string
}
function func(obj: Obj) {
    console.log(obj.label)
}

let obj = {size: 10, label: 'object'}
func(obj)

可选属性"?"

interface SquareConfig {
    color? :string;
    width?: number;
}

function createSquare(config: SquareConfig): {color: string; area: number} {
    let newSquare = {color: 'white', area: 100}
    if (config.color) {
        newSquare.color = config.color
    }
    if (config.width) {
        newSquare.area = config.width * config.width
    }
    return newSquare
}

let mySquare = createSquare({color: 'black'})
console.log(mySquare)

这里"color?"表明color属性为可选, 而{color: string; area: number}表明函数返回值的类型.

只读属性readonly

interface Point {
    readonly x: number,
    readonly y: number,
}

let p1: Point = {x: 10, y: 20}
// error
p1.x = 5

使用ReadonlyArray<T>为只读数组:

let a: number[] = [1, 2, 3, 4]
let ro: ReadonlyArray<number> = a
// error
ro[0] = 12
// error
a = ro

可使用as将只读数组赋值给一般数组:

a = ro as number[]

属性检查

针对上例函数中, 我们调用:

let mySquare = createSquare({colour: 'red', width: 100})

这里TS会直接报错, 因为它认定需要传入的参数为color/width, 没有colour属性.

假定我们程序里要求允许有其它的属性, 则需要修改interface:

interface SquareConfig {
    color?: string,
    width?: number,
    [propName: string]: any,
}

函数类型

我们可定义函数的参数和返回值:

interface SearchFunc {
    (source: string, subString: string): boolean,
}

let mySearch: SearchFunc
mySearch = function(src: string, sub: string): boolean {
    let result = src.search(sub)
    return result > -1
}

let search: SearchFunc
search = function(src, sub) {
    let result = src.search(sub)
    return result > -1
}

这一般适用于大量参数相同的函数的设定.

索引类型

数组的索引, 默认为整数, 但实际上会被转换为字符串. 我们可设定索引类型, 并可设定为只读:

interface StringArray {
    readonly [index: number]: string
}

let myArray: StringArray
myArray = ['Alice', 'Bob']

let myStr: string = myArray[0]
console.log(myStr)
// error
// myStr[2] = 'Mallory'

class类型

我们可以为class定义一个接口:

interface ClockInterface {
    currentTime: Date;
}

class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h: number, m: number) {}
}

我们甚至可以在接口中声明方法, 在类中定义方法:

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) {}
}

如果我们为构造函数实现check:

interface ClockInterface {
    new (hour: number, minute: number);
}

class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h: number, m: number) {}
}

这将报错! 因为TS的class中, 检查的是具体实例. 而构造函数属于静态方法, 无法被检查.

如果要检查构造函数, 只能将构造函数当做一个方法来对待:

interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("beep beep");
    }
}

class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) {}
    tick() {
        console.log("tick tick");
    }
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);

接口扩展

interface Shape {
    color: string;
}
interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

let square = <Square>{};
square.color = 'blue';
square.sideLength = 10;
square.penWidth = 5.0;

console.log(square);

混合类型

interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = <Counter>function (start: number) {};
    counter.interval = 123;
    counter.reset = function () {};
    return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

 

Classes

我们定义一个简单的class: 属性greeting, 构造函数和方法greet

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return `Hello, ${this.greeting}`;
    }
}

let greeter = new Greeter("world");
console.log(greeter.greet());

继承

使用extends关键字实现继承操作:

class Animal {
    name: string;
    constructor(theName: string) { this.name = theName; }
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 5) {
        console.log(`Slithering...`);
        super.move(distanceInMeters);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 45) {
        console.log(`Galloping...`);
        super.move(distanceInMeters);
    }
}

let sam = new Snake(`Sammy the Python`);
let tom: Animal = new Horse(`Tommy the Palomino`);

sam.move();
tom.move(34);

public, private和protected

默认情况下, class的属性/构造函数/方法, 均为public.

private的属性/方法, 只能在本class内部调用. 在外部或者继承中, 无法调用private声明的属性和方法.

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

// error
new Animal('cat').name;

private变量/方法是无法进行比较的, 所以下例中animal = employee会报错:

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

class Rhino extends Animal {
    constructor() { super("Rhino"); }
}

class Employee {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

let animal = new Animal('Goat');
let rhino = new Rhino();
let employee = new Employee('Bob');

animal = rhino;
// error
animal = employee;

protected不仅允许class内部调用, 还允许继承clas调用:

class Person {
    protected name: string;
    constructor(name: string) { this.name = name; }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name);
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee('Howard', 'Sales');
console.log(howard.getElevatorPitch());
// error
console.log(howard.name);

Readonly

我们可以设定属性为只读, 那除了构造函数中进行初始化以外, 其它任何地方都不可以对其进行修改:

class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor(theName: string) {
        this.name = theName;
    }
}

let dad = new Octopus('Man with the 8 strong legs');
// error
dad.name = 'Man with the 3-piece suit';

Static

静态属性与实例无关, 与类有关.

class Grid {
    static origin = {x: 0, y: 0};
    calc(point: {x: number; y: number;}) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor(public scale: number) {}
}

let grid1 = new Grid(1.0);
let grid2 = new Grid(5.0);

console.log(grid1.calc({x: 10, y: 10}));
console.log(grid2.calc({x: 10, y: 10}));

Abstract Classes

抽象类不同于接口在于它可实现其方法:

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log('roaming the earth...');
    }
}

 

函数

一般函数可声明为如下格式:

let myAdd = (x: number, y: number) : number => {
    return x + y;
};

console.log(myAdd(1, 3));

函数中某些参数可选, 或者可指定默认值:

let myAdd = (x: number, y?: number) : number => {
    return x + y;
};

let myAdd1 = (x: number, y = 3) : number => {
    return x + y;
};

剩余参数可使用"..."语法糖:

let func = (x: number, ...rest: any[]) => {
    console.log(rest)
};

func(1, 2, 3, 4);

 

© 著作权归作者所有

共有 人打赏支持
fzyz_sb
粉丝 408
博文 209
码字总数 447144
作品 0
武汉
程序员
TypeScript系列1-简介及版本新特性

简介 随着PC端快速向移动端迁移,移动(体验)优先的概念也越来越响。由于ReactJS目前移动端仅仅支持iOS,因此移动端Web开发框架只能选择: AngularJS/Angula2 + Ionic框架 + Cordova。想要学...

一配
2015/08/15
0
0
TypeScript VS JavaScript 深度对比

TypeScript 和 JavaScript 是目前项目开发中较为流行的两种脚本语言,我们已经熟知 TypeScript 是 JavaScript 的一个超集,但是 TypeScript 与 JavaScript 之间又有什么样的区别呢?在选择开...

powertoolsteam
06/29
0
0
TypeScript 语言学习

开发环境推荐 Visual Studio Code https://code.visualstudio.com 免费, 跨平台, 支持 Windows, OS X 以及 Linux. Visual Studio https://www.visualstudio.com Visual Studio 2015 RC 已整合......

小骏骏
2015/08/06
0
0
TypeScript 2.8引入条件类型

最新发布的TypeScript 2.8包含了若干主要特性和一些问题修复,其中最为重要的是新增了条件类型,开发人员可以根据其他类型的特征为变量选择适当的类型。 条件类型最适合与泛型组合在一起使用...

dotNET跨平台
04/15
0
0
TypeScript开发系列(二)——VS让普通工程自动编译TypeScript

在用Visual Studio 开发TypeScript时,如此系列(一)中所做的那样,只有创建一个Type Application 工程,在此工程中添加的.ts(TypeScript文件格式)脚本在编译时才会自动被编译。如果我们想要...

lhan
2013/01/09
0
0
此生无悔入 TypeScript

↑ 编者按:本文由phodal公众号授权奇舞周刊转载。 想来,我已经用 TypeScript 已经有一段时间了,它可以算得上是前端领域的一门 “平淡生活” 的语言。 平淡生活,我的意思是:生活可以从此...

奇舞周刊
04/26
0
0
让前端的子弹飞-TypeScript

“ Any application that can be written in JavaScript,will eventually be written in JavaScript.” -- Jeff Atwood 2007 “ 前端,文也; 后端,武也; 全栈,文武双全者也; 前端全栈者...

06/22
0
0
5分钟了解TypeScript

1.安装TypeScript 有两种方式安装TypeScript: Via npm 通过安装VS插件,更多可参见这里。 对于npm用户,可以直接使用下面的命令行安装: nmp install -g TypeScript 2.创建第一个TypeScript文...

zhanggui
06/12
0
0
WEB前端学习面试加分题:同学,你了解TypeScript吗?

Web前端开发工程师是一个很新的职业,是从事Web前端开发工作的工程师。主要进行网站开发,优化,完善的工作。网页制作是Web 1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行...

web前端小辰
05/11
0
0
Delphi、C#之父Anders Hejlsberg首次访华 推广TypeScript

Delphi、C#之父Anders Hejlsberg近日首次访华,并在10月24日和27日参加了两场见面会,分享了他目前领导开发的TypeScript项目,并与国内前端开发者近距离交流。InfoQ记者全程参与了两场见面会...

一配
2015/11/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Xshell登录阿里云服务器ECS

Xshell登录阿里云服务器ECS 1. 参考资料: 1). 《阿里云服务器怎么用?阿里云服务器使用教程》 链接:http://www.cr173.com/html/50758_1.html 2). eagle-zhang的CSDN博客《Xshell连接不上阿...

SuShine
4分钟前
0
0
IDEA中的HTTP Client Editor测试API

在前后端分离项目,前后端通过api进行通信。如果用postman免费版进行api测试的话,由于无法保存测试脚本到文件,不方便前端查看。 你可以选择付费版。也可以利用IDEA自带的HTTP Client Edito...

hutaishi
6分钟前
0
0
解决“只能通过Chrome网上应用商店安装该程序”的方法

摘要 : 最近有些用户反映某个Chrome插件在安装的时候,提示“只能通过Chrome网上应用商店安装该程序”,为了解决这一问题,Chrome插件网带来了相关的解决方法。 某些用户在Chrome插件网下载了...

沧海一刀
7分钟前
0
0
通过UNIX域套接字传递文件描述符

  传送文件描述符是高并发网络服务编程的一种常见实现方式。Nebula 高性能通用网络框架即采用了UNIX域套接字传递文件描述符设计和实现。本文详细说明一下传送文件描述符的应用。 1. TCP服务...

Bwar
10分钟前
0
0
python操作Excle

# -*- coding: utf-8 -*-from openpyxl import load_workbook, Workbook#index:第几个sheet页,第一个sheet页的index为0def readExcle(filename,index): # 加载excle文件 wb = l......

淺陌离殇
12分钟前
0
0
Apache爆日志文件漏洞

全球使用最广泛的Web服务器Apache近日被爆出了一个安全漏洞,该漏洞可能导致攻击者控制服务器。 该漏洞包含在mod_rewrite 模块中的do_rewritelog()日志函数中。由于该函数还无法完全过滤写入...

问题终结者
47分钟前
0
0
阿里巴巴内部开发手册

现代软件架构的复杂性需要协同开发完成,如何高效地协同呢?无规矩不成方圆,无规范难以协同,比如,制订交通法规表面上是要限制行车权,实际上是保障公众的人身安全,试想如果没有限速,没有...

zbbmaster
51分钟前
0
0
34.任务计划cron chkconfig systemctl管理服务 unit target

10.23 linux任务计划cron 10.24 chkconfig工具 10.25 systemd管理服务 10.26 unit介绍 10.27 target介绍 10.23 linux任务计划cron: 在linux中任务计划是必不可少的,因为可能我们凌晨的时候...

王鑫linux
51分钟前
0
0
logback.xml for spring boot

logback.xml config <?xml version="1.0" encoding="UTF-8"?><configuration> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.Colo......

qwfys
52分钟前
0
0
告警系统邮件引擎 运行告警系统

告警系统邮件引擎 因为之前做zabbix的时候,做过mail.py的脚本,在这里,直接调用进行使用就可以。 但是告警邮件引擎核心,conf主配置文件调用到的都是mail.sh ,所以这里需要定义调用mail....

lyy549745
52分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部