文档章节

TypeScript学习笔记

fzyz_sb
 fzyz_sb
发布于 2017/08/28 20:25
字数 1822
阅读 173
收藏 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);

 

© 著作权归作者所有

上一篇: CSS学习笔记1
fzyz_sb
粉丝 411
博文 209
码字总数 447144
作品 0
武汉
程序员
私信 提问
TypeScript学习笔记之四接口(Inferfaces)

一、使用环境 Mac 电脑 WebStorm TypeScript3.x版本 二、接口 在 TypeScript 中,我们使用接口(Interfaces)来定义对象的类型,在OOP编程中接口都是比较常见且重要的概念 接口的作用 A、对类...

摸着石头过河_崖边树
2018/12/10
0
0
初探TypeScript 基础篇

前言 由于自己目前在学习typescript;想着边学习变做笔记,往后也可以翻出来看看,也分享出来给像我一样的初学者一起学习。望各位大佬指教。 简介 什么是TypeScript 为什么要选择TypeScript ...

小菜鸡一枚
04/18
0
0
TypeScript学习笔记之六函数(重点箭头函数)

一、使用环境 Mac 电脑 WebStorm TypeScript3.x版本 二、基本函数 2.1、函数声明定义 2.2、函数表达式定义 2.3、用接口定义函数 2.4、函数参数:可选参数 和默认值参数 三、箭头函数 3.1、基...

摸着石头过河_崖边树
2018/12/10
0
0
TypeScript学习笔记之一初见TypeScript

一、什么是TypeScript? TypeScript是一种编译性语言、强类型语言、真正的面向对象 它是JavaScript的一个超集,所以看这个教程的时候最好您具有JavaScript的基础知识 TypeScript开源代码 二、...

摸着石头过河_崖边树
2018/12/05
0
0
Typescript Handbook 精简版之基础类型

简介 Typescript支持与Javascript几乎一样的数据类型:布尔值、数字、字符串,结构体等,此外Typescript还提供了很实用的枚举类型。 Boolean(布尔值) Number(数字) 和Javascript一样,T...

er3456qi
2018/08/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

typescript 接口 函数类型 可索引类型

函数类型 可索引类型 数字索引签名 字符串索引签名 数字索引签名返回值 必须是 字符串索引签名返回值的子集 只读索引签名

lilugirl
今天
3
0
Oracle SQL语法实例合集

如需转载请注明出处https://my.oschina.net/feistel/blog/3052024 目的:迅速激活Oracle SQL 参考:《Oracle从入门到精通》 ------------------------------------------------------------......

LoSingSang
今天
2
0
增加 PostgreSQL 服务进程的最大打开文件数

https://serverfault.com/questions/628610/increasing-nproc-for-processes-launched-by-systemd-on-centos-7 要在systemd的配置里加才行...

helloclia
今天
2
0
组合模式在商品分类列表中的应用

在所有的树形结构中最适合的设计模式就是组合模式,我们看看常用商品分类中如何使用。 先定义一个树形结构的商品接口 public interface TreeProduct { List<TreeProduct> allProducts(...

算法之名
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部