typescript入门笔记自用1 (数据类型和接口)

75 阅读4分钟

基础类型

布尔值、数字、字符串、数组

let boolData: boolean = true
let numData: number = 1
let strData: string = 'abc'
let arrData1: number[] = [1,2,3]
let arrData2: Array<string> = ['a', 'b'] //泛型

元组

元组允许一个已知类型的数组,元组的类型与数组的元素类型一一对应

let arr: [string, number, string] = ['a', 2, 'b']

enum枚举

使用枚举类型可以赋予数组友好的名字(没搞懂使用场景,遇到补充)

enum Color {red, green = 2, yellow}
let c: Color = Color.red
let green: string = Color[2]

any

不对类型进行检查,一般用于:

  1. 对现有代码进行改写,Object虽然允许赋予任何值,但却不允许调用上面的任意方法
let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
  1. 只知道一部分的数据类型时
let arr: any = [1,3,"sb"]
arr.push(true)

void

函数没有返回值return时的类型,如果作为变量的类型,只能赋值为undefindnull

undefind && null

默认情况下nullundefined是所有类型的子类型。 就是说你可以把 nullundefined赋值给number类型的变量。

然而,当你指定了--strictNullChecks标记,nullundefined只能赋值给void和它们各自。 这能避免 很多常见的问题。 也许在某处你想传入一个 stringnullundefined,你可以使用联合类型string | null | undefined

never

never类型表示的是那些永不存在的值的类型。对于函数,一般在抛出错误或while(1){}这种时候使用,对于变量则是那些被永不为真条件约束。总结就是存在无法达到的终点
never是任意类型的子类型,可以赋值给任意类型;没有类型可以赋值给never类型,除了never自身。

function error(message: string): never {
    throw new Error(message);
}

// 推断的返回值类型为never
function fail() {
    return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
    while (true) {
    }
}

Object

object不是原始数据类型,使用object类型可以更好的表示如Object.create这样的方法

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

类型断言

类型断言就是指定一个变量的类型,让ts在编译阶段跳过对这个变量的类型检查,有两种语法格式,我觉得还是用as好点,比较清晰

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
let someValue: any = "this is a string";
let strLength: number = (<string> someValue).length;

接口

接口interface指定了一系列数据的名称以及类型,如果给某个数据指定这一接口,ts就会对其检查,查看是否具有这些数据,类型是否正确,下面定义一个简单的接口

interface person {
    readonly name: string,
    age: number,
    isMarried?: boolean
}

function logPerson(obj: person): void {
    console.log(obj);
}
const obj = {
    name: 'czc',
    age: 35,
    weight: 70
}

logPerson(obj)

可以看到,interface是会对其自身拥有的属性进行检查,且可赋予可选属性key?: type,可选属性的好处是可以对可能存在的属性进行预定义,二是可以捕获不存在属性的错误。
但当interface可选属性和对象字面量一起使用时,就会出现额外的类型检查,按照我自己的理解,就是当你对参数进行带有可选属性 interface约束时,你在传入实参的时候直接传入对象本身(即function({a:1, b:2})),ts会进行额外的检查,即可选属性失效。如下面的例子:

interface SquareConfig {
    color?: string;
    width?: number;
}

function createSquare(config: SquareConfig): { color: string; area: number } {
    return {color:'a', area:1}
}

let mySquare = createSquare({ colour: "red", width: 100 });//// error: 'colour' not expected in type 'SquareConfig'

解决这一问题,有以下几种方法:

  1. 类型断言
let mySquare = createSquare({ colour: "red", width: 100 } as SquareConfig);
  1. 添加一个字符串索引签名
interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any
}
  1. 把参数赋给一个变量
let squareOptions = { colour: "red", width: 100 }; 
let mySquare = createSquare(squareOptions);

函数接口

接口也可以描述函数类型,包括描述参数和返回值

interface fnc {
    (obj: SquareConfig) : boolean
}

let func: fnc;
func = function(config: SquareConfig) {
    return true
}

函数的形参无需与函数接口定义的参数有相同名称

interface SearchFunc {
    (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function (src: string, sub: string): boolean {
    let result = src.search(sub);
    return result > -1;
}

可索引的签名

描述索引,使得数据可以以类似数组的方式取值,索引包括字符串和数字两种,同样可以设置成readOnly

interface NumberDictionary {
    [index: string]: number;
    length: number;    // 可以,length是number类型
    name: string       // 错误,`name`的类型与索引类型返回值的类型不匹配
  }
  interface ReadonlyStringArray {
    readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error!

在类的应用

用到了再补充

混合类型

接口里可以描述不同的数据类型,比如函数,字符串

interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = <Counter>function (start: number) { };
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;