上篇: TS基礎數組
type
type strAria = string; // 給 string 類型定義了 strAria別名
const str: strAria = 'abc';
type fnAria = () => string;
function (callback:fnAria):void {
callback();
}
複製代碼
type EventName = 'xm' | 'xh' | 'xb';
const str : EventName = 'xb'
const elseStr : EventName = 'xf' // error, 不在這幾個名字當中
複製代碼
咱們使用 type
定了一個字符串字面量類型 EventNames
,它只能取三種字符串中的一種。函數
注意,類型別名與字符串字面量類型都是使用 type 進行定義。post
一個帶有不一樣值的數組ui
let confusion: [string,number] = ['a',1]; // 這就叫元組
複製代碼
let confusion: [string, number];
confusion[0] = 'a'; // 能夠只賦值給某一項
confusion[1] = 'b' // error , 元組的第2項必須爲 number
// 若是直接給元組賦值,要徹底提供其定義好的類型和長度
confusion = ['a',1]
複製代碼
當添加越界的元素時,它的類型會被限制爲元組中每一個類型的聯合類型:this
let xcatliu: [string, number];
xcatliu = ['Xcat Liu', 25]; // ok
xcatliu.push('http://xcatliu.com/'); // ok
xcatliu.push(true); // error, 不能添加非字符串和 number 的值
複製代碼
用於定義一個類型的值在必定的範圍內spa
使用
enum
定義枚舉code枚舉的成員從0開始遞增,而且key 和 value 會互相映射xml
enum Colors { Red, Yellow, Blue }
Colors['Red'] === 0 // true 從0開始遞增
Colors[0] === 'Red' // 相互映射
// 枚舉事實上會編譯成以下
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Yellow"] = 1] = "Yellow";
Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));
複製代碼
枚舉的值是能夠二次賦值的,被從新賦值的後一項會接着上一項的key遞增對象
若是兩個枚舉值重複了,不會報錯,可是值會被覆蓋繼承
能夠爲小數或者負數,遞增步數仍然爲 1
配合斷言,可讓枚舉不是數字
enum Colors { Red = 1, Yellow, Blue }
Colors['Red'] = 2 // 從新賦值
Colors['Yellow'] // 3 下一項 + 1
Colors['Yellow'] = 1 // 此時 Red 和 Blue 值重複了, Colors[2] 只會取最後的值,由於覆蓋了。
console.log(Colors[2] === "Red"); // false
console.log(Colors[2] === "Blue"); // true
// 負數
Colors['Red'] = 2.1
Colors['Yellow'] // 3.1
複製代碼
enum Colors { Red = 1, Yellow, Blue = <any>"S" } Colors['Blue'] // 'S' 複製代碼
上面咱們使用的枚舉都是常數項
計算所得項就是經過計算賦值的枚舉,只在編譯階段求值
enum Colors { Red = 1, Yellow, Blue = 1 + 1 }
// 因爲編譯時求值 計算所得項的後一項若是沒有賦值,會由於沒法得到初始值報錯
enum Colors { Red = 'asdasd'.length, Yellow, Blue } // error
複製代碼
當知足如下條件時,枚舉成員被看成是常數:
1
。但第一個枚舉元素是個例外。若是它沒有初始化方法,那麼它的初始值爲 0
。+
, -
, ~
一元運算符應用於常數枚舉表達式+
, -
, *
, /
, %
, <<
, >>
, >>>
, &
, |
, ^
二元運算符,常數枚舉表達式作爲其一個操做對象。若常數枚舉表達式求值後爲 NaN 或 Infinity,則會在編譯階段報錯全部其它狀況的枚舉成員被看成是須要計算得出的值。
enum Colors { Red, Yellow, Blue }
// Colors['Red'] ==> 0 Colors['Yellow'] ==> 1 Colors['Blue'] ==> 2
enum Directions {
Up = 996,
Down = Up,
Left = Colors['Red'],
Right = (1 + 1),
UpLeft = 2 % 1,
DownLeft = 'a' - 1, // 結果 NaN 報錯
}
複製代碼
使用 const enum
定義的枚舉
常數枚舉與普通枚舉的區別是,它會在編譯階段被刪除,而且不能包含計算成員。
const enum Color {Red, Green, Blue = "blue".length};// error 不能包含計算成員
複製代碼
使用 declare enum
定義的枚舉類型
declare
定義的類型只會用於編譯時的檢查,編譯結果中會被刪除。
外部枚舉與聲明語句同樣,常出如今聲明文件中。
同時使用 declare
和 const
也是能夠的:
類用於面向對象
接口用於對象形狀的描述
不一樣的類之間某一部分可能行爲一致,那麼爲了避免重複寫兩個同樣的接口,可使用implements
實現重用interface
implements
中文譯爲 "實現"
好比有個狗類,有個貓類,它們都有 eat 這個方法,實現的形狀一致
interface Behavior {
eat(food: string): void
}
class Dog implements Behavior {
eat(foot) {}
}
class Cat implements Behavior {
eat(foot) {}
}
class habaDog extends Dog implements Behavior {
// 此時哈巴狗繼承了狗類,就有了 eat 方法
}
複製代碼
interface Behavior { // 行爲接口
eat(food: string): void
}
interface Appearance { // 外表接口
fur:string
}
class Dog implements Behavior {
eat(foot) {}
}
class habaDog extends Dog implements Behavior, Appearance {
fur = ''
}
複製代碼
接口也是能夠繼承接口的
繼承老爸姓名
interface Fa {
surname: string
}
interface Son extends Fa {
name: string
}
const obj: Son = {
surname : 'z',
name: 'zc'
}
複製代碼
用於將某個 class 定義爲類型,並往上再添加類型。
class Fa {
constructor() {}
suck(){
}
}
interface Son extends Fa {
suck():void;
name: string;
}
複製代碼
指在定義函數、接口或類的時候,不預先指定具體的類型,而在使用的時候再指定類型的一種特性。
使用
<T>
表明類型的變量, T 只是約定用法,能夠任意指定。
function getArrVal<T>(something:T):Array<T> {
return [something];
}
getArrVal<string>('z') // ['z'] 使用時再指定類型
getArrVal('z') // 不寫也沒事 ts 會推論出來
// 接口型定義
interface Test<T> {
num : T
}
let o : Test<string> = {
num: '1'
}
複製代碼
interface Test<T,U> {
name?: T,
num : U
}
let o : Test<string,number> = {
num: 1
}
function Test<T,U> (a:T,b:U):void { // 函數定義
console.log(a,b);
}
Test<string,number>('1',1)
複製代碼
泛型沒法知道具體的類型,因此沒法操做它的屬性和方法
function Test<T> (a:T):void {
console.log(a.length); // error
}
Test<string>('1')
複製代碼
當你明確知道泛型中有哪些屬性方法時,能夠經過 extends
進行泛型約束,寫在聲明函數名的後面
interface hasLengthProp {
length : number;
}
function Test<T extends hasLengthProp>(a:T):void {
console.log(a.length);
}
複製代碼
至關於泛型的繼承
function test<T extends U,U>(a:T,b:U):void {
console.log(a);
}
test({a:1,b:2,c:3},{a:1,b:2})
複製代碼
在接口中定義泛型,若是接口中只定義了一個匿名函數的類型,直接賦值便可。
interface Test {
<T>(name:T):void
}
let say:Test; // 直接賦值
say = function<T>(name:T):void {
console.log(name);
}
say('haha')
複製代碼
若是接口中包含多個屬性,這個接口就是一個對象的描述
interface Test {
demo<T>(name:T):void;
a:string;
}
let say:Test; // 對象的描述
say.demo = function<T>(name:T):void {
console.log(name);
}
say.demo('haha')
複製代碼
就是在泛型裏面使用類型變量 類那節說過,類有兩部分:靜態部分和實例部分。 泛型類指的是實例部分的類型,因此類的靜態屬性不能使用這個泛型類型
class Name<T>{
num:T;
constructor(num:T) {
this.num = num
}
add:(x:T,y:T) => T;
}
let addName = new Name<number>(10)
addName.num = 10
addName.add = (x:number,y:number) => {
return 1+2
}
複製代碼
當代碼中沒有直接指定,而且類型推論也沒有成功時,默認值會生效
function say<T = any>(name: T):void {
alert(name)
}
say<string>('1') // ok
say(true) // ok
複製代碼
就是說聲明兩個一樣的接口、類或者函數,會進行合併操做。
合併的屬性的類型必須是惟一的
interface Alarm {
price: number;
alert(s: string): string;
}
interface Alarm {
weight: number;
alert(s: string, n: number): string;
}
===> 至關於
interface Alarm {
price: number;
weight: number;
alert(s: string, n: number): string;
}
複製代碼