这样学TS,迟早进大厂系列(第二期)
江左梅郎: 一个对开发技术特别执着的程序员,对移动开发有着独到的见解和深入的研究,有着多年的H5开发经验,对NativeApp、HybridApp、WebApp开发有着独到的见解和深入的研究, 除此之外还精通 JavaScript、AngularJS、 NodeJS 、Ajax、jQuery、Cordova、Vue、React Native等多种Web前端技术及Java、PHP等服务端技术。
TS从初级到高级 第七期.
更新中…
初学者玩转 TypeScript系列,总计 10 期,本文为第 2 期,点赞、收藏、评论、关注、三连支持!
对于初学者来说,学习编程最害怕的就是,难。
那么,Typescript 是不是很难?
首先,我可以肯定地告诉你,你的焦虑是多余的。新手对学习新技术有很强的排斥心理,主要是因为基础不够扎实,然后自信心不够强。
1. 变量声明和解构?
-
TS中变量声明和解构和ES6一样
-
详见 ES6 相关知识
2. 接口的基本使用
-
什么是接口类型?
-
和 number,string,boolean,enum 这些数据类型一样
-
接口也是一种类型, 也是用来约束使用者的
* */
// 定义一个接口类型
interface FullName{
firstName:string
lastName:string
}
let obj = {
firstName:'Jonathan',
lastName:'Lee'
// lastName:18
};
// 需求: 要求定义一个函数输出一个人完整的姓名
// 这个人的姓必须是字符串, 这个人的名也必须是一个字符
function say({firstName, lastName}:FullName):void {
console.log(`我的姓名是:${firstName}_${lastName}`);
}
say(obj);
3.可选属性和索引签名
- 定义一个接口
interface FullName{
firstName:string
lastName:string
middleName?:string
[propName:string]:any
}
- 需求: 如果传递了 middleName 就输出完整名称, 如果没有传递middleName, 那么就输出 firstName 和 lastName
function say({firstName, lastName, middleName}:FullName):void {
// console.log(`我的姓名是:${firstName}_${lastName}`);
if(middleName){
console.log(`我的姓名是:${firstName}_${middleName}_${lastName}`);
}else{
console.log(`我的姓名是:${firstName}_${lastName}`);
}
}
// 注意点: 如果使用接口来限定了变量或者形参, 那么在给变量或者形参赋值的时候,
// 赋予的值就必须和接口限定的一模一样才可以, 多一个或者少一个都不行
// say({firstName:'Jonathan'});
// say({firstName:'Jonathan', lastName:'Lee', middleName:"666"});
// 注意点: 但是在企业开发中可以多一个也可能少一个
// 少一个或多个怎么做? 可选属性
// say({firstName:'Jonathan', lastName:'Lee', middleName:"666"});
// say({firstName:'Jonathan', lastName:'Lee'});
// 多一个或者多多个怎么做? 如果绕开TS检查
// 方式一: 使用类型断言
// say({firstName:'Jonathan', lastName:'Lee', middleName:"666", abc:'abc'} as FullName);
// 方式二: 使用变量
// let obj = {firstName:'Jonathan', lastName:'Lee', middleName:"666", abc:'abc'};
// say(obj);
// 方式三: 使用索引签名
say({firstName:'Jonathan', lastName:'Lee', middleName:"666", abc:'abc', 123:123, def:"def"});
4. 函数接口和混合类型接口
- 函数接口
- 我们除了可以通过接口来限定对象以外, 我们还可以使用接口来限定函数
/*
interface SumInterface {
(a:number, b:number):number
}
let sum:SumInterface = function (x:number, y:number):number {
return x + y;
}
let res = sum(10, 20);
console.log(res);
*/
// 混合类型接口
// 约定的内容中既有对象属性, 又有函数
// 要求定义一个函数实现变量累加
/*
let count = 0; // 会污染全局空间
function demo() {
count++;
console.log(count);
}
demo();
demo();
demo();
*/
/*
let demo = (()=>{ // 使用闭包确实可以解决污染全局空间的问题, 但是对于初学者来说不太友好
let count = 0;
return ()=>{
count++;
console.log(count);
}
})();
demo();
demo();
demo();
*/
// 在JS中函数的本质是什么? 就是一个对象
// let demo = function () {
// demo.count++;
// }
// demo.count = 0;
// demo();
// demo();
// demo();
interface CountInterface {
():void
count:number
}
let getCounter = (function ():CountInterface {
/*
CountInterface接口要求数据既要是一个没有参数没有返回值的函数
又要是一个拥有count属性的对象
fn作为函数的时候符合接口中函数接口的限定 ():void
fn作为对象的时候符合接口中对象属性的限定 count:number
* */
let fn = <CountInterface>function () {
fn.count++;
console.log(fn.count);
}
fn.count = 0;
return fn;
})();
getCounter();
getCounter();
getCounter();
5. 接口的继承
- 接口的继承
- TS中的接口和JS中的类一样是可以继承的
interface LengthInterface {
length:number
}
interface WidthInterface {
width:number
}
interface HeightInterface {
height:number
}
interface RectInterface extends LengthInterface,WidthInterface,HeightInterface {
// length:number
// width:number
// height:number
color:string
}
let rect:RectInterface = {
length:10,
width:20,
height:30,
color:'red'
}
6. TypeScript 函数
- TS中的函数
- TS中的函数大部分和JS相同
// 命名函数
function say1(name) {
console.log(name);
}
// 匿名函数
let say2 = function (name) {
console.log(name);
}
// 箭头函数
let say3 = (name) => {
console.log(name);
}
// 命名函数
function say1(name:string):void {
console.log(name);
}
// 匿名函数
let say2 = function (name:string):void {
console.log(name);
}
// 箭头函数
let say3 = (name:string):void =>{
console.log(name);
}
7. 函数的声明与重载
// TS函数完整格式
// 在TS中函数的完整格式应该是由函数的定义和实现两个部分组成的
/*
// 定义一个函数
let AddFun:(a:number, b:number)=>number;
// 根据定义实现函数
AddFun = function (x:number, y:number):number {
return x + y;
};
let res = AddFun(10, 20);
console.log(res);
*/
/*
// 一步到位写法
let AddFun:(a:number, b:number)=>number =
function (x:number, y:number):number {
return x + y;
};
let res = AddFun(20, 20);
console.log(res);
*/
/*
// 根据函数的定义自动推导对应的数据类型
let AddFun:(a:number, b:number)=>number =
function (x, y) {
return x + y;
};
let res = AddFun(20, 20);
console.log(res);
*/
// TS函数声明
/*
// 先声明一个函数
type AddFun = (a:number, b:number)=>number;
// 再根据声明去实现这个函数
// let add:AddFun = function (x:number, y:number):number {
// return x + y;
// };
let add:AddFun = function (x, y) {
return x + y;
};
let res = add(30, 20);
console.log(res);
*/
// TS函数重载
// 函数的重载就是同名的函数可以根据不同的参数实现不同的功能
/*
function getArray(x:number):number[] {
let arr = [];
for(let i = 0; i <= x; i++){
arr.push(i);
}
return arr;
}
function getArray(str:string):string[] {
return str.split('');
}
*/
// 定义函数的重载
function getArray(x:number):number[];
function getArray(str:string):string[];
// 实现函数的重载
function getArray(value:any):any[] {
if(typeof value === 'string'){
return value.split('');
}else{
let arr = [];
for(let i = 0; i <= value; i++){
arr.push(i);
}
return arr;
}
}
// let res = getArray(10);
let res = getArray('www.it666.com');
console.log(res);
8. 泛型
- 什么是泛型?
- 在编写代码的时候我们既要考虑代码的健壮性, 又要考虑代码的灵活性和可重用性
- 通过TS的静态检测能让我们编写的代码变得更加健壮, 但是在变得健壮的同时却丢失了灵活性和可重用性
所以为了解决这个问题TS推出了泛型的概念 - 通过泛型不仅可以让我们的代码变得更加健壮, 还能让我们的代码在变得健壮的同时保持灵活性和可重用性
// 需求: 定义一个创建数组的方法, 可以创建出指定长度的数组, 并且可以用任意指定的内容填充这个数组
/*
let getArray = (value:number, items:number = 5):number[]=>{
return new Array(items).fill(value);
};
// let arr = getArray(6, 3);
let arr = getArray("abc", 3); // 报错
console.log(arr);
*/
/*
let getArray = (value:any, items:number = 5):any[]=>{
return new Array(items).fill(value);
};
// let arr = getArray("abc", 3);
let arr = getArray(6, 3);
// console.log(arr);
// 当前存储的问题:
// 1.编写代码没有提示, 因为TS的静态检测不知道具体是什么类型
// 2.哪怕代码写错了也不会报错, 因为TS的静态检测不知道具体是什么类型
let res = arr.map(item=>item.length); // ['abc', 'abc', 'abc'] => [3, 3, 3]
console.log(res);
*/
// 需求:要有代码提示, 如果写错了要在编译的时候报错
let getArray = <T>(value:T, items:number = 5):T[]=>{
return new Array(items).fill(value);
};
// let arr = getArray<string>('abc');
// let arr = getArray<number>(6);
// 注意点: 泛型具体的类型可以不指定
// 如果没有指定, 那么就会根据我们传递的泛型参数自动推导出来
let arr = getArray('abc');
// let arr = getArray(6);
let res = arr.map(item=>item.length);
console.log(res);
9. 泛型约束
- 什么是泛型约束?
- 默认情况下我们可以指定泛型为任意类型
但是有些情况下我们需要指定的类型满足某些条件后才能指定
那么这个时候我们就可以使用泛型约束
// 需求: 要求指定的泛型类型必须有Length属性才可以
interface LengthInterface{
length:number
}
let getArray = <T extends LengthInterface>(value:T, items:number = 5):T[]=>{
return new Array(items).fill(value);
};
let arr = getArray<string>('abc');
// let arr = getArray<number>(6);
let res = arr.map(item=>item.length);
码字不易,在线求个三连支持。
大家记得收藏前,先点个赞哦!好的文章值得被更多人看到。
最后,再多一句,粉丝顺口溜,关注江哥不迷路,带你编程上高速。
版权所有,请勿转载,转载请联系本人授权
支付宝生态技术学习交流群