上篇: 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;
}
复制代码