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

被折叠的 条评论
为什么被折叠?



