TS学习日记day2 - typescript基础内容
基本数据类型
原始数据类型
Booleans(布尔值),number(数值),string(字符串),null,undefined,以及Es6中的新类型Symbol
空值
JS 中没有空值(Void)的概念,在 TS 中,可以用 void 表示没有任何返回值的函数,声明一个 void 类型的变量没什么用,因为你只能将它赋值为 undefined 和 null
null 和 undefined:在 TS 中,可以使用 null 和 undefined 来定义这两个原始数据类型
null、undefined 和 void 的区别:undefined 和 null 时所有类型的子类型,也就是说 undefined 类型的变量,可以赋值给 number 类型的变量。
//布尔值 let x: boolean = false; console.log(x); // 数值 支持其他进制 let num1: number = 6; let num2: number = 0b1010; let num3: number = 0o744; console.log(num1, num2, num3); // 字符串 let str: string = 'dada'; console.log(str); // null 和 undefined let a: undefined = undefined; let b: null = null; // undefined 和 null 可以赋值给任何类型 【然而,当你指定了--strictNullChecks标记,null和undefined只能赋值给void和它们各自。】 // let c: number = undefined; // let d: undefined; // let e: number = d; console.log(a, b);
任意值Any。==> 已经被 unknown 代替
任意值(Any)用来表示允许赋值为任意类型。如果是一个普通类型,在它赋值过程中改变类型时不允许的。但是 any 类型是可以被赋值为任意类型的。
当一个变量在声明时没有规定它的类型,他就会默认声称为 任意值(Any)
let any: any = 'seven'; console.log(any);//seven any = 7; console.log(any);//7 let some; console.log(some);//undefined some = 7; console.log(some);//7 some = 'string'; console.log(some);//string
void
用于标识方法返回值的类型,表示该方法没有返回值。
function hello(): void { alert("Hello Runoob"); }
never
never 是其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。这意味着声明为 never 类型的变量只能被 never 类型所赋值,在函数中它通常表现为抛出异常或无法执行到终止点(例如无限循环),示例代码如下:
let x: never; let y: number; // 运行错误,数字类型不能转为 never 类型 x = 123; // 运行正确,never 类型可以赋值给 never类型 x = (()=>{ throw new Error('exception')})(); // 运行正确,never 类型可以赋值给 数字类型 y = (()=>{ throw new Error('exception')})(); // 返回值为 never 的函数可以是抛出异常的情况 function error(message: string): never { throw new Error(message); } // 返回值为 never 的函数可以是无法被执行到的终止点的情况 function loop(): never { while (true) {} }
类型推论
let a = 'string'// ==> let a:string = 'string' a = 7;//报错
联合类型
联合类型(Union Types) 表示取值可以为多种类型中的一种,不同类型之间用 | 分割。
let a: string | number; a = 'string'; console.log(a);//string a = 7; console.log(a);//7
访问联合类型的属性和方法:
当 TS 不确定一个联合类型的变量到底是哪个类型的时候,我门只能访问此联合类型的所有类型里共有的属性或方法。
function getLength(something: string | number) :number{ return something.length//报错 类型“string | number”上不存在属性“length”->类型“number”上不存在属性“length”。 } let a :string|number a = 'string' console.log(a.length)// 6 根据类型推论此时 a 为 string 类型,所以有 length 属性 a = 7 console.log(a.length)//报错 根据类型推论此时 a 为 number 类型,所以没有 length 属性
接口
在 TS 中,我们使用接口 (interfaces) 来定义对象类型
interface Person{ name:string, age:number } let Ann:Person ={ name:'Ann', age:33, // title:"nihao" 赋值时 变量不能比接口多,也不能比接口少 } console.log(Ann.name,Ann.age)
可选属性
interface Person { name: string; age: number; title?: string;//可选属性,可有可没有 } let Ann: Person = { name: 'Ann', age: 33, title: 'nihao'//有没有都不会报错 }; console.log(Ann.name, Ann.age);
任意属性
interface Person { name: string; age: number; title?: string;//可选属性,可有可没有 [propName:string]:unknown /* propName 是属性名字,propName:string 是指这个属性的名字是 string 类型。 [propName:string]:unknow 是指属性的值是 any [propName:string]:unknow 可以对应多个 属性 注意:一但定义了任意属性,那么确定属性和可选属性的类型都必须是任意属性他的类型的子集。 */ } let Ann: Person = { name: 'Ann', age: 33, title: 'nihao',//有没有都不会报错 some1: 4, some2:"any", }; console.log(Ann.name, Ann.age);
interface Person { name: string; age: number;//age:number 不是 string 类型的子集 所以会报错 title?: string; [propName:string]:string //如果 age 必须是 number 类型 那么任意类型可以改成如下 就不会在报错来 // [propName:string]:string | number; } let Ann: Person = { name: 'Ann', age: 33, title: 'nihao', some1: 'any' }; console.log(Ann.name, Ann.age);
只读属性
只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候。
interface Person { readonly id: number; name: string; age: number; title?: string; [propName: string]: unknown; } let Ann: Person = { id:0, name: 'Ann', age: 33, title: 'nihao' }; Ann.id = 1//报错 只读属性只有在第一次定义时可以赋值,之后不可以再次更改
数组
数组的定义有多种方式,比较灵话
[类型 + 方括号]表示法
let num:number[] = [1,2,3,4]
console.log(num)
注意:数组中不可以存在其他类型
let num:number[] = [1,2,{},3,4]//报错,数组的项中不允许出现其他的类型 console.log(num)
数组泛型
let a:Array<number> =[1,2,3,4,5] console.log(a) // let a:Array<number> =[1,2,{},3,4,5] 也不允许出现其他的类型
接口
interface Num { [index:number]:number; } let a:Num = [1,1,3,4,5] console.log(a)
类数组
类数组不是数组类型,例如 argument
function sum() { let a:number[] = arguments;//报错 类数组不可以单纯的使用一个数组来描述 } function sum2(){ let a:{ [index:number]:number } = arguments ////类数组需要使用一个接口来描述 }
any 在数组中的应用
let list :any[] = [1,2,3,4,'num'] // let list :unknown[] = [1,2,3,4,'num'] console.log(list)
函数
定义函数的方式:函数声明、函数表达式。
// 函数声明 function sum1(x, y) { return x + y; } // 函数表达式 let sum2 = function(x, y) { return x + y; };
let sum = function(x: number, y: number): number { return x + y; }; console.log(sum(1, 1)); /* 这种是可以通过编译的,但是这段代码只对等号右侧的匿名函数进行了类型的定义。 而等号左边的 sum 是通过赋值操作进行类型推论而推断出来的,如果需要我们手动给 sum 添加类型,则应该是如下: */ // 箭头左边是传入 箭头右侧是输出 let mySum: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; };
// 可选参数一定在必须参数后面 function buildName(firstName:string,lastName?:string){ if(lastName){ return firstName + ' ' + lastName }else{ return firstName } } let Tom = buildName('tom','cat') let ken = buildName('ken') console.log(ken)
参数默认值
function buildName(firstName:string,lastName:string='moren'){ if(lastName){ return firstName + ' ' + lastName }else{ return firstName } } let Tom = buildName('tom') console.log(Tom)//tom moren
剩余参数
有一种情况,我们不知道要向函数传入多少参数,这时候我们就可以使用剩余参数来定义。剩余参数语法允许我们将一个不确定数量的参数作为一个数组传入
function buildName(firstName: string, ...lastName: string[]) { return firstName + ' ' + lastName; } let Tom = buildName('tom', 'b', 'c');//b,c 相当于一个数组传进来了。 console.log(Tom);
元组
数组合并了相同的对象,而元组合并了不同类型的对象。
let tom:[string,number] tom = ['tom',12] console.log(tom)//[ 'tom', 12 ]
枚举
枚举类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝。
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; //枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射: console.log(Days["Sun"] === 0); // true console.log(Days["Mon"] === 1); // true console.log(Days["Tue"] === 2); // true console.log(Days["Sat"] === 6); // true console.log(Days[0] === "Sun"); // true console.log(Days[1] === "Mon"); // true console.log(Days[2] === "Tue"); // true console.log(Days[6] === "Sat"); // true
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat}; //未手动赋值的枚举项会接着上一个枚举项递增。 //如果未手动赋值的枚举项与手动赋值的重复了,TypeScript 是不会察觉到这一点的: console.log(Days["Sun"] === 7); // true console.log(Days["Mon"] === 1); // true console.log(Days["Tue"] === 2); // true console.log(Days["Sat"] === 6); // true
enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat}; //递增到 3 的时候与前面的 Sun 的取值重复了,但是 TypeScript 并没有报错 //导致 Days[3] 的值先是 "Sun",而后又被 "Wed" 覆盖了。所以使用的时候需要注意,最好不要出现这种覆盖的情况。 //手动赋值的枚举项可以不是数字,此时需要使用类型断言来让 tsc 无视类型检查 (编译出的 js 仍然是可用的): console.log(Days["Sun"] === 3); // true console.log(Days["Wed"] === 3); // true console.log(Days[3] === "Sun"); // false console.log(Days[3] === "Wed"); // true
enum Days {Sun = 7, Mon = 1.5, Tue, Wed, Thu, Fri, Sat}; //动赋值的枚举项也可以为小数或负数,此时后续未手动赋值的项的递增步长仍为 1 console.log(Days["Sun"] === 7); // true console.log(Days["Mon"] === 1.5); // true console.log(Days["Tue"] === 2.5); // true console.log(Days["Sat"] === 6.5); // true
转自:https://www.cnblogs.com/zzalmo/p/11280529.html
类型断言
类型断言的用途:
讲一个联合类型断言为其中一个类型
讲任何一个类型断言为any
jiangany断言为一个具体的类型
interface cat { name: string; // age:number run(): void; } interface fish { name: string; // age:number swim(): void; } function getName(animals: cat | fish) { // return animals.name; if (typeof (animals as fish).swim == 'function') { return true; } else { return false; } } const jj: cat = { name: 'jj', run() { console.log('run'); } }; getName(jj) // 会报错,编译没有错误,但是运行会有错误
const a:number = 1; // window.a = 1//报错 (window as any).a = 1;