参考文档:github.com/zhongsp/Typ…git
在像c#和Java这样的语言中,建立 可重用组件 的工具箱中的一个主要工具是泛型,也就是说,可以建立能够在多种类型上工做的组件,而不是单个类型。这容许用户使用这些组件并使用本身的类型es6
function clone(a:any):any{
return a;
}
复制代码
function clone<T>(a:T):T{
return a;
}
let r1=clone<string>("haha"); // r1:string
let r2=clone<number>(1); // r2:number
// 能够不明确传入类型,编译器会自动推断
let r3=clone(true); // r3:boolean
复制代码
把泛型当作变量做为类型的一部分使用github
function logger<T>(args:Array<T>):Array<T>{
console.log(args.length);
return args;
}
复制代码
也能够以下这么写:json
function logger<T>(args:T[]):T[]{
console.log(args.length);
return args;
}
复制代码
function clone<T>(arg: T): T {
return arg;
}
let f1: <T>(arg: T) => T = clone;
// 也可使用带有调用签名的对象字面量定义
let f2: { <T>(arg: T): T } = clone;
// 泛型接口
interface GenericFn{
<T>(arg:T):T
}
interface GenericFn2<T>{
(arg:T):T
}
let f3: GenericFn = clone;
let f3: GenericFn2<string> = clone;
复制代码
class Queue<T> {
private data: T[] = [];
push = (item: T) => this.data.push(item);
pop = (): T | undefined => this.data.shift();
}
// 简单的使用
const queue = new Queue<number>();
queue.push(0);
queue.push("1"); // Err: 接受的始类型应为 number
复制代码
extends
关键字interface ILength {
length: number;
}
function logger<T extends ILength>(n: T) {
return n.length;
}
复制代码
function getProp<T, K extends keyof T>(obj: T, prop: K) {
return obj[prop];
}
let o = {
name: "aaa",
age: 111,
}
getProp(o,"name");
getProp(o,"age");
getProp(o,"b"); // Err 对象 "o" 上不存在属性 "b"
复制代码
function createInstance<T>(Ctor: { new(): T }):T {
return new Ctor;
}
复制代码
enum Direction {
Up, // 0
Right, // 1
Down, // 2
Left // 3
}
复制代码
enum ServerCode {
BadRequest = 400, // 400
NoAuth, // 401
BanAccess = 403, // 403
NotFound, // 404
ServerError = 500 // 500
}
复制代码
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
复制代码
混入数字和字符串成员的枚举c#
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
复制代码
枚举是运行时真正存在的对象数组
enum E {
X,
Y,
Z
}
function f(obj: { X: number }) {
return obj.X;
}
f(E)
复制代码
enum LogLevel {
ERROR,
WARN,
INFO,
DEBUG
}
type LogLevelStrings = keyof typeof LogLevel;
let status: LogLevelStrings = "ERROR";
status="666"; // Err: "666" 不能赋值给 "ERROR" | "WARN" | "INFO" | "DEBUG"
复制代码
const
枚举常量枚举不容许包含计算成员(只容许使用常量枚举表达式)dom
const enum Enum {
A = 1,
B = 2 * A, // ok 常量枚举表达式
C = Math.random(), // Err: 计算成员
D = (() => 1)() // Err: 计算成员 } 复制代码
在正常的枚举里,没有初始化方法的成员被当成常量成员。 对于很是量的外部枚举而言,没有初始化方法时被当作须要通过计算的编辑器
declare enum Enum {
A = 1,
B,
C = 2
}
复制代码
同时拥有全部类型的所有成员函数
interface IA {
name: string;
}
interface IB {
age: number;
}
let d: IA & IB = {
name: "",
age: 1
};
复制代码
只能是全部类型之一工具
function printSth(input: string | number) {
return input;
}
printSth(1);
printSth("");
interface IC {
name: string;
c: number;
}
复制代码
若是值是联合类型,只能访问全部类型的公有部分
interface IC {
name: string;
c: number;
}
interface ID {
name: string;
d: string;
}
function f3(): IC | ID {
return {
name: "",
c: 1
};
}
let c3 = f3();
c3.name;
c3.d; // Err: 联合类型,只能访问全部类型里公有的部分
复制代码
使用联合类型的值时,须要类型区分出明确的类型
用户定义类型守卫
as
let pet = getSmallPet();
if ((pet as Fish).swim) {
(pet as Fish).swim();
} else if ((pet as Bird).fly) {
(pet as Bird).fly();
}
复制代码
使用类型断定
is
function isFish(pet:Fish|Bird):pet is Fish {
return (pet as Fish).swim!==void 0;
}
复制代码
in
操做符function move(pet:Fish|Bird) {
if ("swim" in pet) {
pet.swim();
} else {
pet.fly();
}
}
复制代码
typeof
类型守卫
function padLeft(m: string | number) {
if (typeof m === "number") {
return m + 1;
} else {
return m.trim();
}
}
复制代码
instanceof
类型守卫function move2(pet: Fish | Bird) {
if (pet instanceof Fish) {
return pet.swim();
} else {
return pet.fly();
}
}
复制代码
null
的类型默认状况下,
null
和undefined
能够赋值给任何类型,开启 "--strictNullChecks" 标记解决此错误
使用了 "--strictNullChecks" 标记,可选参数会被自动加上 "|undefined"
interface IA{
// name:string|undefined
name?:string;
age:number
}
复制代码
因为使用联合类型,可能会包含
null
类型,你须要使用类型守卫去除它
function f1(s:string|null){
if (s===null) return;
return s+"haha";
}
复制代码
function f1(s:string|null){
let char=s||"";
return s+"haha";
}
复制代码
!
,去除 null
和 undefined
编辑器没法去除嵌套函数的
null
和undefined
,因此须要添加语法后缀!
,来去除null
和undefined
function f11(s: string | null) {
s = s || "";
function f12() {
return s!.toString();
}
return f12();
}
复制代码
// 基础类型
type NewString = string;
// 函数
type TypeOfFn = (arg: string) => string;
// 泛型
type GenericObj<T> = {
value: T;
};
type Tree<T> = {
value: string;
left: Tree<T>;
right: Tree<T>;
} | null;
复制代码
类型别名 vs 接口
type A={
name: string;
};
// Err: 标识 "A" 重复
type A={
age: string;
};
interface IA {
name: string;
}
// ok
interface IA {
age: number;
}
let a: IA = {
name: "",
age: 1
};
复制代码
type Easing = "ease-in" | "ease-out";
let status3: Easing = "ease-in";
status3="a"; // Err
复制代码
function createElement(tagName: "img"): HTMLImageElement;
function createElement(tagName: "input"): HTMLInputElement;
// ... more overloads ...
function createElement(tagName: string): Element {
// ... code goes here ...
if (tagName === "img") {
return new Image();
}
if (tagName === "input") {
return document.createElement("input");
}
return document.createElement("div");
}
createElement("input");
createElement("img");
复制代码
function sayCode(a: 1 | 2 | 3) {
return a + 1;
}
sayCode(1);
sayCode(5); // Err
复制代码
使用索引类型,能够检查动态属性名
keyof
,为 索引类型查询操做符
T[K]
,为 索引访问操做符
let o3 = {
a: 1,
b: "2",
c: true
};
function f8<T, K extends keyof T>(obj: T, prop: K): T[K] {
return obj[prop];
}
f8(o3, "b");
f8(o3, "a");
f8(o3, "d"); // Err: 不存在属性 "d"
复制代码
索引类型和字符串签名
keyof T
的结果会是 number|string
,由于 js 中,object[1]
和 object["1"]
均可以访问属性interface Dictionary {
[key: string]: any;
}
let keys: keyof Dictionary; // keys:string | number
复制代码
keyof T
的结果会是 number
interface Dictionary {
[key: number]: any;
}
let keys: keyof Dictionary; // keys:number
复制代码
type Readonly<U> = {
readonly [T in keyof U]: U[T];
};
type Partial<U> = {
[T in keyof U]?: U[T];
};
type ReadonlyPerson = Readonly<IPerson>;
type PartialPerson = Partial<IPerson>;
复制代码
// 这样使用 使用交叉类型
type PartialWithNewMember<T> = {
[P in keyof T]?: T[P];
} & { newMember: boolean };
// 不要这样使用这会报错!
type PartialWithNewMember<T> = {
[P in keyof T]?: T[P];
newMember: boolean;
}
复制代码
T extends U ? X : Y
翻译: 若是 T
能赋值给 U
,那么类型是 X
,不然是 Y
type Partial<T>={
[P in keyof T]?:T[P]
}
复制代码
type Required<T>={
// "-?" 表明去除可选 对应的还有 "+?" ,做用与 "-?" 相反,是把属性变为可选项
[P in keyof T]-?:T[P]
}
复制代码
type Readonly<T>={
readonly [P in keyof T]:T[P]
}
复制代码
type Record<K extends keyof any,T>={
[P in K]:T
}
复制代码
type Exclude<T,U>=T extends U?never:T;
复制代码
type Extract<T,U>=T extends U?T:never;
复制代码
type Pick<T,K extends keyof T>={
[P in K]:T[P]
}
复制代码
type Omit<T,K extends keyof any>=Pick<T,Exclude<keyof T,K>>
复制代码
type NonNullable<T>=T extends null|undefined? never: T;
复制代码
type ReturnType<T extends (...args:any)=>any>=T extends (...args:any)=> infer R ? R : any;
复制代码
type InstanceType<T extends new (...args:any):any> = T extends new (...args:any):infer R ? R : any;
复制代码
interface ThisType<T>{
}
复制代码
ts 沿用 es6 的模块概念
StringValidator.ts
export interface StringValidator {
isSafe:boolena;
}
复制代码
test.ts
import { StringValidator } from "./StringValidator";
class Validator implements StringValidator {
isSafe:boolean = true;
}
复制代码
StringValidator.ts
export default {
version: "1.1.1"
}
复制代码
导入其余 js 库 (要想描述非 TypeScript 编写的类库的类型,咱们须要声明类库所暴露出的 API )
utils.d.ts
declare module "url" {
export function parse() {
// ...
}
}
复制代码
test.ts
/// <reference path="utils.d.ts" />
import { parse } from "url";
复制代码
简写模块里全部导出的类型将是 any
utils.d.ts
declare module "url";
复制代码
test.ts
/// <reference path="utils.d.ts" />
import { parse } from "url";
// parse:any
复制代码
global.d.ts
declare module "*.json";
复制代码
namespace Validation {
export interface StringValidator {
isSafe:boolena;
}
export class Validator implements StringValidator {
isSafe:boolean = true;
}
}
复制代码
Validation.ts
namespace Validation {
export interface StringValidator {
isSafe:boolena;
}
}
复制代码
KlassValidation.ts
/// <reference path="Validation.ts" />
namespace Validation {
export class Validator implements StringValidator {
isSafe:boolean = true;
}
}
复制代码
namespace Validation {
export interface StringValidator {
isSafe:boolena;
}
}
import SV = Validation.StringValidator;
复制代码
为了描述不是用 TypeScript 编写的类库的类型,咱们须要声明类库导出的API。 因为大部分程序库只提供少数的顶级对象,命名空间是用来表示它们的一个好办法。
咱们称其为声明是由于它不是外部程序的具体实现。 咱们一般在.d.ts
里写这些声明
D3.d.ts
declare namespace D3 {
export interface Selectors {
select: {
(selector: string): Selection;
(element: EventTarget): Selection;
};
}
export interface Event {
x: number;
y: number;
}
export interface Base extends Selectors {
event: Event;
}
}
declare var d3: D3.Base;
复制代码