Typescript 快速上手(笔记)

本文详细介绍了如何快速上手TypeScript,包括安装、泛型的使用(如泛型函数、泛型类、泛型约束)以及枚举的详细概念,如数字枚举、字符串枚举、枚举的类型兼容性。此外,还探讨了类型推论在 TypeScript 中的作用以及类型兼容性的规则。

快速学习Typescript

简介: typescript 是JavaScript 的一个超集,它可以编译成纯JavaScript,Typescript可以再任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。–官方的说法
本文只记js中未出现的概念 如 泛型、枚举、类型推论、高级类型等

一、安装

  • 通过npm安装
	npm install -g typescript

写入下面的代码到你的ts文件

function greeter(person) {
    return "Hello, " + person;
}

let user = "Jane User";

document.body.innerHTML = greeter(user);

cd folder(你的文件夹)
tsc example.ts (编译你的ts文件)
会生成 example.js 文件
打开看看—应该差不多

二、泛型

泛型只可以指代多种数据类型的一种类型 一般用 表示泛型
举例: Hello world

//常规
function indentity(arg: number): number{
	return arg
}
//假如我们这里要求参数类型可以是string
//用 any实现
function identity(arg: any): any{
	return arg
}
//使用泛型实现
function identity<T>(arg: T): T{
	return arg;
}

使用T型数组

function loggingIdentity<T>(arg: T[] : T[]){
	console.log(arg.length);
	return arg
}

//同上
function loggingIdentity<T>(arg: Array<T>) : Array<T>{
	console.log(arg.length);
	return arg;
}

使用不同的泛型参数名

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: <U>(arg:U) => U = indenitty

使用带有调用签名的对象字面量来定义泛型函数:

function identity<T>(arg: T) : T {
	return arg;
}

let myIdentity: {<T>(arg: T) : T} = indentity;

泛型类

class GenericNumber<T>{
	zeroValue: T;
	add: (x: T,y: T) => T
}

let myGenericNumber = new GenericNumber<number>();
myGenericName.zeroValue = 0;
myGenericNumber.add = function(x,y) {
	return x + y;
}

泛型约束
使用接口

interface Lengthwise {
	length: number;
}
function loggingIdentity<T extens Lengthwise>(arg: T) : T{
	console.log(arg.length); //不报错
	return arg
}

在泛型约束中使用 类型参数

function getProperty(obj: T, key: K) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.

在泛型里使用类类型

function create<T>(c: {new(): T; }): T {
    return new c();
}

三、枚举

枚举使用 关键字 enum 定义
数字枚举(默认)

enum Direction{
	Up,
	Down,
	Left,
	Right
} //Up值为 0 Down值 为1 Left 值为 2 Right值为3
//初始化 Up值为1
enmu Direction{
	Up = 1,
	Down,
	Left,
	Right
}// Up = 1 Down = 2 ...

使用枚举

enum Response{
	No = 0,
	Yes = 1
}

function respond (recipient: string,message: Response: Response) : void{
	//...
}
respond('Princess Caroline',Response.Yes);

字符串枚举

enum Direction{
	Up = 'UP',
	Down = "DOWN",
	Left = "LEFT",
	Right = "RIGHT"
}

异构枚举

enum BooleanEnum{
	No = 0,
	Yes = "YES"
}

计算和常量成员

enum FileAccess {
	None,
	Read = 1 << 1,
	Write = 1<< 2,
	Reawrite = Read | Write,
	G = '123'.length
}

联合枚举与枚举成员的类型

enum ShapeKind{
	Circle,
	Square
}

interface Circle{
	kind: ShapeKind.Circle;
	radius: number
}
interface Square{
	kind: ShapeKind.Square;
	sideLength: number;
}

let c: Circle  = {
	kind: ShapeKind.Square,
	//    ~~~~~~~~~~~~~~~~ Error!
	radius: 100
}

运行时的枚举

enum E {
	X,Y,Z
}
function f(obj: {X: number}){
	return obj.X
}
//Works, since 'E' has a property named 'X' is a number.

反向映射

enum Enum{
	A
}
let a = Enum.A;

const 枚举

const enum Enum{
	A = 1,
	B = A * 2
}

外部枚举

declare enum Enum{
	A = 1,
	B,
	C = 2
}

四、类型推论

基础
Typescript 里,在有些没有明确指出类型的地方,类型推论会帮助提供类型

let x = 3; //x 被推断为数字
let zoo = [new Rhino(),new Elephant(), new Snake()];

//为了推断为 Animal 需要明确指出类型

let zoo: Animal[] = [new Rhino(),new Elephant(), new Snake()];

最佳通用类型
let x = [0,1,null]

上下文类型

window.onmousedown = function(mouseEvent){
	console.log(mouseEvent.button);  // <- Error
} 

这个例子会得到一个类型错误,TypeScript类型检查器使用Window.onmousedown函数的类型来推断右边函数表达式的类型。 因此,就能推断出 mouseEvent参数的类型了。 如果函数表达式不是在上下文类型的位置, mouseEvent参数的类型需要指定为any,这样也不会报错了。

如果上下文类型表达式包含了明确的类型信息,上下文的类型被忽略。 重写上面的例子:

window.onmousedown = function(mouseEvent: any) {
    console.log(mouseEvent.button);  //<- Now, no error is given
};

五、类型兼容

开始
TypeScript结构化类型系统的基本规则是,如果x要兼容y,那么y至少具有与x相同的属性,例如:

interface Named{
	name: string;
}

let x: Named;

let y = { name: 'Alice', location: 'Seattle'};
x = y;

这里y包含字段name 因此可以赋值 反过来则不行

函数参数双向协定
当比较函数参数类型时,只有当源函数参数能够赋值给目标函数或者反过来时才能赋值成功。 这是不稳定的,因为调用者可能传入了一个具有更精确类型信息的函数,但是调用这个传入的函数的时候却使用了不是那么精确的类型信息。 实际上,这极少会发生错误,并且能够实现很多JavaScript里的常见模式。例如:

enum EventType { Mouse, Keyboard }

interface Event { timestamp: number; }
interface MouseEvent extends Event { x: number; y: number }
interface KeyEvent extends Event { keyCode: number }

function listenEvent(eventType: EventType, handler: (n: Event) => void) {
    /* ... */
}

// Unsound, but useful and common
listenEvent(EventType.Mouse, (e: MouseEvent) => console.log(e.x + ',' + e.y));

// Undesirable alternatives in presence of soundness
listenEvent(EventType.Mouse, (e: Event) => console.log((<MouseEvent>e).x + ',' + (<MouseEvent>e).y));
listenEvent(EventType.Mouse, <(e: Event) => void>((e: MouseEvent) => console.log(e.x + ',' + e.y)));

// Still disallowed (clear error). Type safety enforced for wholly incompatible types
listenEvent(EventType.Mouse, (e: number) => console.log(e));

可选参数及剩余参数
比较函数兼容性的时候,可选参数与必须参数是可互换的。 源类型上有额外的可选参数不是错误,目标类型的可选参数在源类型里没有对应的参数也不是错误。

function invokeLater(args: any[], callback: (...args: any[]) => void) {
    /* ... Invoke callback with 'args' ... */
}

// Unsound - invokeLater "might" provide any number of arguments
invokeLater([1, 2], (x, y) => console.log(x + ', ' + y));

// Confusing (x and y are actually required) and undiscoverable
invokeLater([1, 2], (x?, y?) => console.log(x + ', ' + y));

枚举
枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。不同枚举类型之间是不兼容的。比如,

enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };

let status = Status.Ready;
status = Color.Green;  // Error

class Animal {
    feet: number;
    constructor(name: string, numFeet: number) { }
}

class Size {
    feet: number;
    constructor(numFeet: number) { }
}

let a: Animal;
let s: Size;

a = s;  // OK
s = a;  // OK

泛型
因为TypeScript是结构性的类型系统,类型参数只影响使用其做为类型一部分的结果类型。比如,

interface Empty<T> {
}
let x: Empty<number>;
let y: Empty<string>;

x = y;  // OK, because y matches structure of x

上面代码里,x和y是兼容的,因为它们的结构使用类型参数时并没有什么不同。 把这个例子改变一下,增加一个成员,就能看出是如何工作的了:

interface NotEmpty<T> {
    data: T;
}
let x: NotEmpty<number>;
let y: NotEmpty<string>;

x = y;  // Error, because x and y are not compatible

对于没指定泛型类型的泛型参数时,会把所有泛型参数当成any比较。 然后用结果类型进行比较,就像上面第一个例子。

比如,

let identity = function<T>(x: T): T {
    // ...
}

let reverse = function<U>(y: U): U {
    // ...
}

identity = reverse;  // OK, because (x: any) => any matches (y: any) => any
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值