參考文檔: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;
複製代碼