这样学TS,迟早进大厂系列(第四期)
江左梅郎: 一个对开发技术特别执着的程序员,对移动开发有着独到的见解和深入的研究,有着多年的H5开发经验,对NativeApp、HybridApp、WebApp开发有着独到的见解和深入的研究, 除此之外还精通 JavaScript、AngularJS、 NodeJS 、Ajax、jQuery、Cordova、Vue、React Native等多种Web前端技术及Java、PHP等服务端技术。
TS从初级到高级 第七期.
更新中…
初学者玩转 TypeScript系列,总计 10 期,本文为第 4 期,点赞、收藏、评论、关注、三连支持!
对于初学者来说,学习编程最害怕的就是,难。
那么,Typescript 是不是很难?
首先,我可以肯定地告诉你,你的焦虑是多余的。新手对学习新技术有很强的排斥心理,主要是因为基础不够扎实,然后自信心不够强。
1.数字枚举和字符串枚举
- TS中支持两种枚举, 一种是数字枚举, 一种是字符串枚举
- 数字枚举
- 默认情况下就是数字枚举
enum Gender{
Male,
Female
}
console.log(Gender.Male);
console.log(Gender.Female);
- 数字枚举注意点
- 数字枚举的取值默认从0开始递增
- 数字枚举的取值可以是字面量, 也可以是常量, 也可以是计算的结果
const num = 666;
function getNum() {
return 888;
}
enum Gender{
// Male = 6,
// Male = num, // 注意点: 如果使用常量给前面的枚举值赋值了, 那么后面的枚举值也需要手动的赋值
// Female = 8
Male = getNum(), // 注意点: 如果使用计算结果给前面的枚举值赋值了, 那么后面的枚举值也需要手动的赋值
Female = 123
}
- 枚举反向映射
// 可以根据枚举值获取到原始值 // 也可以根据原始值获取到枚举值 enum Gender{ Male, Female } console.log(Gender.Male); // 0 console.log(Gender[0]); // Male
enum Gender{ Male = 'www.it666.net', Female = 'www.itzb.net' // 注意点: 如果使用字符串给前面的枚举值赋值了, 那么后面的枚举值也必须手动赋值 } console.log(Gender.Male); console.log(Gender.Female);
- 字符串枚举注意点
- 注意点: 如果使用字符串给前面的枚举值赋值了, 那么后面的枚举值也必须手动赋值
- 注意点: 和数字枚举不一样, 字符串枚举不能使用常量或者计算结果给枚举值赋值
- 注意点: 虽然字符串枚举不能够使用常量或者计算结果给枚举值赋值, 但是它可以使用内部的其它枚举值来赋值
const str = 'lnj';
function getStr() {
return 'abc';
}
enum Gender{
Male = 'www.it666.net',
// Male = str,
// Male = getStr(),
Female = 'www.itzb.net',
Yao = Female
}
console.log(Gender.Female);
console.log(Gender.Yao);
- 异构枚举
- 枚举中既包含数字又包含字符串, 我们就称之为异构枚举
enum Gender{
Male = 6,
Female = 'nv'
}
console.log(Gender.Male);
console.log(Gender.Female);
console.log(Gender[6]);
// 注意点: 如果是字符串枚举, 那么无法通过原始值获取到枚举值
// console.log(Gender['nv']);
console.log(Gender);
2. 枚举成员类型和联合类型
-
枚举成员类型
-
我们就可以把枚举成员当做类型来使用
enum Gender{
Male = 'www.it666.com',
Female = 'www.itzb.com'
}
interface TestInterface {
age: Gender.Male
}
class Person implements TestInterface{
age: Gender.Male
// age: Gender.Female // 由于类型不匹配, 所以会报错
// age: 0 // 注意点: 由于数字枚举的本质就是数值, 所以这里写一个数值也不会报错
// age: Gender.Male
// age: Gender.Female
// age: 'www.it666' // 注意点: 如果是字符串枚举, 那么只能是枚举成员的值, 不能是其它的值
// age: string
}
- 联合枚举类型
- 什么是联合类型?
- 联合类型就是将多种数据类型通过|连接起来
- 我们可以把枚举类型当做一个联合类型来使用
let value:(number | string); // (number | string)联合类型 value = 1; value = 6; value = "123"; enum Gender{ Male , Female } interface TestInterface { age: Gender // age: (Gender.Male | Gender.Female) } class Person implements TestInterface{ // age: Gender.Male age: Gender.Female }
3.运行时和常量枚举
// 运行时枚举 // 枚举在编译之后是一个真实存储的对象, 所以可以在运行时使用 // 而像接口这种只是用来做约束做静态检查的代码, 编译之后是不存在的 interface TestInterface { name:string; age:number; } enum Gender{ Male, Female }
// 普通枚举和常量枚举的区别 // 普通枚举会生成真实存在的对象 // 常量枚举不会生成真实存在的对象, 而是利用枚举成员的值直接替换使用到的地方 enum Gender1{ Male, Female } console.log(Gender1.Male === 0); const enum Gender2{ Male, Female } console.log(Gender2.Male === 0);
4. 类型推论
- 什么是自动类型推断?
- 不用明确告诉编译器具体是什么类型, 编译器就知道是什么类型
// 1.根据初始化值自动推断
// 如果是先定义在初始化, 那么是无法自动推断的
// let value;
// value = 123;
// value = false;
// value = 'abc';
// 如果是定义的同时初始化, 那么TS就会自动进行类型推荐
// let value = 123; // let value:number = 123;
// value = 456;
// value = false;
// value = 'abc';
let arr = [1, 'a']; // let arr:(number | string) = [1, 'a'];
arr = ['a', 'b', 'c', 1, 3, 5, false]
sm language-ts has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">// 2.根据上下文类型自动推断
window.onmousedown = (event)=>{
console.log(event.target);
}
5. 类型兼容性
// 基本兼容性
/*
interface TestInterface {
name:string;
}
let p1 = {name:'lnj'};
let p2 = {age:18};
let p3 = {name:'lnj', age:18};
let t:TestInterface;
t = p1;
t = p2;
t = p3; // 可多不可少
*/
/*
interface TestInterface {
name:string;
children:{
age:number
};
}
let p1 = {name:'lnj', children:{age:18}};
let p2 = {name:'lnj',children:{age:'abc'}};
let t:TestInterface;
t = p1;
t = p2; // 会递归检查
*/
6. 函数兼容性
// 参数个数
/*
let fn1 = (x:number, y:number)=>{};
let fn2 = (x:number)=>{};
fn1 = fn2;
fn2 = fn1; // 可少不可多
*/
// 参数类型
/*
let fn1 = (x:number)=>{};
let fn2 = (x:number)=>{};
let fn3 = (x:string)=>{};
fn1 = fn2;
fn2 = fn1;
fn1 = fn3; // 必须一模一样
fn3 = fn1;
*/
// 返回值类型
/*
let fn1 = ():number=> 123;
let fn2 = ():number=> 456;
let fn3 = ():string=> 'abc';
fn1 = fn2;
fn2 = fn1;
fn1 = fn3; // 必须一模一样
fn3 = fn1;
*/
// 函数双向协变
/*
// 参数的双向协变
// let fn1 = (x:(number | string)) =>{};
// let fn2 = (x:number) =>{};
// fn1 = fn2;
// fn2 = fn1;
// 返回值双向协变
let fn1 = (x:boolean):(number | string) => x ? 123 : 'abc';
let fn2 = (x:boolean):number => 456;
// fn1 = fn2; // 但是可以将返回值是具体类型的赋值给联合类型的
fn2 = fn1; // 不能将返回值是联合类型的赋值给具体类型的
*/
// 函数重载
function add(x:number, y:number):number;
function add(x:string, y:string):string;
function add(x, y) {
return x + y;
}
function sub(x:number, y:number):number;
function sub(x, y) {
return x - y;
}
// let fn = add;
// fn = sub; // 不能将重载少的赋值给重载多的
let fn = sub;
fn = add; // 可以将重载多的赋值给重载少
7. 枚举兼容性
// 数字枚举与数值兼容
/*
enum Gender{
Male,
Female
}
let value:Gender;
value = Gender.Male;
value = 1
*/
// 数字枚举与数字枚举不兼容
/*
enum Gender{
Male, // 0
Female // 1
}
enum Animal{
Dog, // 0
Cat // 1
}
let value:Gender;
value = Gender.Male;
value = Animal.Dog; // 报错
*/
// 字符串枚举与字符串不兼容
/*
enum Gender{
Male = 'abc',
Female = 'def'
}
let value:Gender;
value = Gender.Male;
value = 'abc';
*/
8. 类兼容性
// 只比较实例成员, 不比较类的构造函数和静态成员
/*
class Person {
public name:string;
// public age:number;
public static age:number;
constructor(name:string, age:number){}
}
class Animal {
public name:string;
constructor(name:string){}
}
let p: Person;
let a: Animal;
p = a;
a = p; // 可多不少
*/// 类的私有属性和受保护属性会响应兼容性
/*
class Person {
protected name:string;
}
class Animal {
protected name:string;
}
let p: Person;
let a: Animal;
p = a;
a = p; // 可多不少
*/
9. 泛型兼容性
// 泛型只影响使用的部分, 不会影响声明的部分
interface TestInterface<T> {
// age:T;
}
let t1: TestInterface<number>; // age:number
let t2: TestInterface<string>; // age:string
t1 = t2;
t2 = t1;
码字不易,在线求个三连支持。
大家记得收藏前,先点个赞哦!好的文章值得被更多人看到。
最后,再多一句,粉丝顺口溜,关注江哥不迷路,带你编程上高速。
版权所有,请勿转载,转载请联系本人授权
支付宝生态技术学习交流群