class Button { buttonName: string; } class SpriteSheet { spriteSheetName: string; } class MovieClip { delay: number; } class Transform { /** readonly typescript 2.0 */ readonly x: number; readonly y: number; } /** * specail */ class PrivatePublicProtectedConstructor { constructor(private a: number, private b: number, public c: number, protected d: string) { } execute() { } } let c = new PrivatePublicProtectedConstructor(1, 2, 3, '11'); c.c; export class TypeExample { constructor() { } execute() { } /** * 数组与元组 * 元组 typescript 1.3 */ executeArrayAndTuple() { // let numberDatas: number[] = [1, 2, 3]; let numberDatas: Array = [1, 2, 3]; //mix type array let mixTypeArray: (number | string | boolean)[] = ['1', 1, true]; // let errorData: [string, number] = [1, 2, 3]; let correctData: [string, number] = ['1', 2]; } /** * typescript 1.4 * 普通字符串与模板字符串(ES6) */ executeTemplateString() { //普通字符串 let commonStr = "export class TypeExample {\n"; commonStr += "\tconstructor() {\n"; commonStr += "\n"; commonStr += "\t}\n"; commonStr += "\n"; commonStr += "\texecute() {\n"; commonStr += "\n"; commonStr += "\t}\n" commonStr += "}"; console.log(commonStr); console.log('-----------------------------------------'); //模板字符串 let className = `TypeScript`; let templateStr = `export class ${className} { constructor() { } execute() { } }`; console.log(templateStr); } /** * 枚举 */ executeEnum() { //普通数字 enum Color { Red, Blue, Green }; //可以存储字符串,我们通常可以用这个定义常 enum Color2 { Red = "Red", Blue = "Blue", Green = "Green" }; } /** * 类型别名 */ executeAliases() { let data: number | string | boolean | number[] | string[] | boolean[]; let getValue = (data: number | string | boolean | number[] | string[] | boolean[]) => { return data; }; //如果有多处地方用到同样混合类型的,可以通过type将这些混合类型定义一某个特定类型,如: type ComplexType = number | string | boolean | number[] | string[] | boolean[]; let _data: ComplexType; let _getValue = (data: ComplexType) => { return data; } } /** * * 联合与交叉类型 TODO */ executeUnionAndIntersectionTypes() { /** ------------------联合类型 typescript 1.4 ------------------- */ class CommandClass { name: string; } interface CommandOptions { commandline: string | string[] | Function | CommandClass; } let commandOptions: CommandOptions; //使用类型保护可以获取某种特定类型的类型 if (typeof commandOptions.commandline === "string") { //typeof string let stringCommandLine = commandOptions.commandline; } else if (typeof commandOptions.commandline === "function") { let functionCommandLine = commandOptions.commandline; } else if (commandOptions.commandline instanceof CommandClass) { let classCommandLine = commandOptions.commandline; } else { let arrayCommandLine = commandOptions.commandline; } /** ------------------交叉类型 typescript 1.6------------------- */ interface AA { nameA: string; } interface AA { ageA: number; } interface BB { nameB: string; } interface CC { nameC: string; } type intersectionType = AA & BB & CC; let data: intersectionType; data.nameA; data.nameB; data.nameC; data.ageA; //通常继承链中会比较常用 function extend(first: T, second: U): T & U { let result = {}; for (let id in first) { (result)[id] = (first)[id]; } for (let id in second) { if (!result.hasOwnProperty(id)) { (result)[id] = (second)[id]; } } return result; } //------------------parameter is Type---------------// interface Bird { fly(); layEggs(); } interface Fish { swim(); layEggs(); } function isFish(pet: Fish | Bird): pet is Fish { return (pet).swim !== undefined; } function getSmallPet(): Fish | Bird { // ... return undefined; } let pet = getSmallPet(); pet.layEggs(); // okay // pet.swim(); // errors type LinkedList = T & { next: LinkedList }; interface Person { name: string; } let people: LinkedList; var s = people.name; var s = people.next.name; var s = people.next.next.name; var s = people.next.next.next.name; interface A { a: string } interface B { b: string } interface C { c: string } var abc: A & B & C; abc.a = "hello"; abc.b = "hello"; abc.c = "hello"; //----------------------更好的联合与交叉类型-------------------------// type Maybe = T | void; function isDefined(x: Maybe): x is T { return x !== undefined && x !== null; } let a = isDefined(10); } /** * 类型推论、断言、保护 */ executeTypeInferenceAndAssertions() { //类型推论 let value = "this is a value"; let value2 = 100; let value3 = [1, 2, 3, 4, 'hello']; for (let i = 0; i < value3.length; i++) { console.log(value3[i]); } let x = [0, 1, 'as']; //这里必须考虑所有元素的类型,所以取其联合类型 console.log(x[1].toString()); //获取所有的 let sprites = [new Button(), new SpriteSheet(), new MovieClip()]; sprites.forEach(value => { if (value instanceof Button) { value.buttonName; } else if (value instanceof SpriteSheet) { value.spriteSheetName; } else if (value instanceof MovieClip) { value.delay; } }); /**-------------------------上下文类型--------------------------- */ window.onmousedown = function (mouseEvent) { console.log(mouseEvent.button); //<- Error }; /**-------------------------类型断言--------------------------- */ class DisplayObject { name: string; uid: number; x: number; y: number; width: number; height: number; scaleX: number; scaleY: number; } class DisplayObjectContainer extends DisplayObject { touchEnabled: boolean; addChild: (child: DisplayObject) => DisplayObject; removeChild: (child: DisplayObject) => DisplayObject; } class Sprite extends DisplayObject { graphics: any; } let balls = [new DisplayObjectContainer(), new Sprite()]; //类型断言 (balls[1] as Sprite).graphics; let ball = balls[1]; //类型保护 if (ball instanceof Sprite) { console.log(ball.graphics); } //*---------------------------------------可推断出真实的类型---------------------------------*/ interface Square { kind: "square"; size: number; } interface Rectangle { kind: "rectangle"; width: number; height: number; } interface Circle { kind: "circle"; radius: number; } type Shape = Square | Rectangle | Circle; function area(s: Shape) { // 下面的 switch 语句中,每个 case 子句都限制了 s 的类型。 // 根据对标识属性值的判断,这使得既然不申明类型也可以根据推断出来的类型访问其它属性。 switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; } } /** ----------------------------typescript 2.7------------------------------------------ */ //更精确的类型推断,切换到typescript 2.6.3会报错 let bar = Math.random() < 0.5 ? { a: true, aData: 100 } : { b: true, bData: "hello" }; if (bar.b) { bar.bData.toLowerCase(); } else { bar.aData.toFixed(2); } } /** * 幂运算符 */ executeExponentiation() { let value = 2 ** 3; } /** 字符串字面量类型 */ executeStringLiteralTypes() { /** typescript 1.8 */ interface AnimationOptions { easeing: "ease-in" | "ease-out" | "ease-in-out"; } } /** * 只读属性 * typescript 2.0 */ executeReadonly() { let transform = new Transform(); // transform.x = 1; } /** * this * typescript 2.0 */ executeThis() { class OOO { mp: number; hp: number; } let o = { func: function (this: OOO) { console.log(this.mp); } } o.func(); } /** never类型 TODO */ executeNeverType() { function error(message: string): never { throw new Error(message); } function fail() { return error("Something failed"); } } /** * typescript 2.1 * 索引访问类型 * */ executeIndexAccessType() { class Rect { x: number; y: number; width: number; height: number; toString: () => void; } type XType = Rect['x']; type ToStringType = Rect['toString']; //在泛型里可以这样: function getProperty(obj: T, key: K) { return obj[key]; // 推断类型是T[K] } } /** * typescript 2.1 * 映射类型 */ executeMapTypes() { //目标:使用现有类型,并使用属性完成可选 interface Person { name: string; age: number; location: string; } // type Partial = { // [K in keyof T]?: T[K]; // } type PartialPerson = Partial; //等价于 // interface PartialPerson { // name?: string; // age?: number; // location?: string; // } //readonly // type Readonly = { // readonly [K in keyof T]?: T[K]; // } type ReadonlyPerson = Readonly; //将每个属性映射成Promise type PromiseValue = { [K in keyof T]: Promise; }; //同样我们可以对任何属性进行映射成任意的,如: type Validator = { callback: (object: T, key: string, componentName: string, ...rest: any[]) => void }['callback']; type ValidatorMap = { [K in keyof T]?: Validator }; class BaseClass { mp: number; hp: number; } let baseClass: ValidatorMap; baseClass.hp(new BaseClass(), '', ''); baseClass.mp(new BaseClass(), '', ''); type PromisePerson = PromiseValue; //proxy type ProxyValue = { [K in keyof T]: { get(): T[K]; set(v: T[K]): void; }; } //在标准库中我们定义了一些常用的映射类型 // Partial 将对象所有的属性变成可选 // Readonly 将对象所有的属性变成可读 // Required 将对象所有的属性变成必选 // Pick 从对象中取可用的属性 // Record // Exclude // Extract // NonNullable // ReturnType // InstanceType //1、Partical作用 interface UserData { /** 玩家正在进行游戏的游戏服务器serverid,非appid */ activeGame: number; /** 由游戏编号与玩家id生成的玩家游戏ID */ gid: number; /** 玩家头像url */ headImgUrl: string; /** 用户最后登录时间 */ lastLoginTime: number; /** 玩家昵称 */ nickName: string; /** 用户中心refreshtoken */ refreshToken: string; /** 用户中心accessToken 非微信端accessToken */ accessToken: string; /** 用户注册时间 */ regTime: number; /** 用户性别 */ sex: number; /** 玩家项目游戏id */ userId: number; /** 用户ip */ userIp: string; /** 用户身份,目前有普通玩家0和GM身份1,新注册玩家999 */ userRole: number; } //惰性附值的时候 class UserDataMrg { private data: Partial = {}; setGid(gid: number) { this.data.gid = gid; } } class BaseObject { hp: number; mp: number; width?: number; height?: number; } type PartialType = Partial; type ReadOnlyType = Readonly; type RequiredType = Required; type PickType = Pick; type RecordType = Record<"mp", BaseObject>; } /** * typescript 2.2 * 对象类型 * 如果函数参数中只能传对象,不能传比如number、string、boolean等基本类型,那么,typescript2.2中新增的object类型可以处理 * 之前的做法是传any或者,不传类型,这种情况下无法约束为对象类型。 * */ executeObjectType() { let setState = (object: object) => { //todo }; setState({ a: 1 }); // setState(1);//error } }