TS 类型保护
这两个部分不那么重要,记点可能用的上的
类型保护就是通过关键字判断出分支中的类型
typeof
function double(input: string | number | boolean) {
if (typeof input === "string") {
return input + input;
} else {
if (typeof input === "number") {
return input * 2;
} else {
return !input;
}
}
}
instanceof
class Animal {
name!: string;
}
class Bird extends Animal {
swing!: number;
}
function getName(animal: Animal) {
if (animal instanceof Bird) {
console.log(animal.swing);
} else {
console.log(animal.name);
}
}
null 保护
开启了 strictNullChecks 选项,那么对于可能为 null 的变量不能调用它上面的方法和属性
function getFirstLetter(s: string | null) {
//第一种方式是加上null判断
if (s == null) {
return "";
}
//第二种处理是增加一个或的处理
s = s || "";
return s.charAt(0);
}
//它并不能处理一些复杂的判断,需要加非空断言操作符
function getFirstLetter2(s: string | null) {
function log() {
console.log(s!.trim());
}
s = s || "";
log();
return s.charAt(0);
}
链判断运算符(?)
a?.b; //如果a是null/undefined,那么返回undefined,否则返回a.b的值.
a == null ? undefined : a.b;
可辨识的联合类型
在 interface 或 type 定义时 写好用于辨识的字段
interface WarningButton{
class:'warning',
text1:'修改'
}
interface DangerButton{
class:'danger',
text2:'删除'
}
type Button = WarningButton|DangerButton;
function getButton(button:Button){
if(button.class=='warning'){
console.log(button.text1);
}
if(button.class=='danger'){
console.log(button.text2);
}
in 判断type的属性
interface Bird { swing: number; }
interface Dog { leg: number; }
function getNumber(x: Bird | Dog) {
if ("swing" in x) {
return x.swing;
}
return x.leg;
}
is 自定义类判断
interface Bird {
swing: number;
}
interface Dog {
leg: number;
}
//没有相同字段可以定义一个类型保护函数
function isBird(x:Bird|Dog): x is Bird{
return (<Bird>x).swing == 2;
//return (x as Bird).swing == 2;
}
function getAnimal(x: Bird | Dog) {
if (isBird(x)) {
return x.swing;
}
return x.leg;
}
类型变换
类型推断
TS能根据赋值,推断 没用定义类型的变量的类型
let foo = 1; // foo 是 'number'
let bar = 'zhufeng'; // bar 是 'string'
foo = bar; // Error: 不能将 'string' 赋值给 `number`
const person = {
name: 'zhufeng',
age: 11
};
let name =person.name;
let age =person.age;
age = 'hello'; // Error:不能把 'string' 类型赋值给 'number' 类型
& 交叉类型
把多个类型拼成一个类型,具有所有类型的所需属性
interface Bird {
name: string,
fly(): void
}
interface Person {
name: string,
talk(): void
}
type BirdPerson = Bird & Person;
let p: BirdPerson = { name: 'zhufeng', fly() { }, talk() { } };
p.fly;
p.name
p.talk;
typeof 获取变量的类型,反射?
//先定义变量,再定义类型
let p1 = {
name:'zhufeng',
age:10,
gender:'male'
}
type People = typeof p1;
function getName(p:People):string{
return p.name;
}
getName(p1);
[]获取一个type内的子type
interface Person{
name:string;
age:number;
job:{
name:string
};
interests:{name:string,level:number}[]
}
let FrontEndJob:Person['job'] = {
name:'前端工程师'
}
let interestLevel:Person['interests'][0]['level'] = 2;
keyof 创建联合类型
interface Person{
name:string;
age:number;
gender:'male'|'female';
}
type PersonKey = keyof Person;
//type PersonKey = 'name'|'age'|'gender';
其他:模块
在默认情况下,当你开始在一个新的 TypeScript 文件中写下代码时,它处于全局命名空间中
这样的话,明明是不同的文件,却会产生命名冲突.
在工作中编码时却并没发现这种不同文件的同名冲突情况,
这是因为,
如果在你的 TypeScript 文件的 根级别位置含有 import 或者 export,
那么它会在这个文件中创建一个本地的作用域,称为 文件模块
AMD:不要使用它,它仅能在浏览器工作;
SystemJS:这是一个好的实验,已经被 ES 模块替代;
ES 模块:它并没有准备好。