当前位置:首页 » 《关注互联网》 » 正文

初学者这样玩 TypeScript,迟早进大厂系列(第七期)_李南江

20 人参与  2021年08月23日 14:03  分类 : 《关注互联网》  评论

点击全文阅读


极客江南: 一个对开发技术特别执着的程序员,对移动开发有着独到的见解和深入的研究,有着多年的iOS、Android、HTML5开发经验,对NativeApp、HybridApp、WebApp开发有着独到的见解和深入的研究, 除此之外还精通 JavaScript、AngularJS、 NodeJS 、Ajax、jQuery、Cordova、React Native等多种Web前端技术及Java、PHP等服务端技术。

初学者玩转 TypeScript系列,总计 10 期,本文为第 7 期,点赞、收藏、评论、关注、三连支持!

一期知识点击这里

二期知识点击这里

三期知识点击这里

四期知识点击这里

五期知识点击这里

六期知识点击这里

七期目录

        • 1.infer关键字
        • 2. unknown
        • 3. 迭代器和生成器
        • 4. 映射类型
        • 5. 模块系统
        • 6. 命名空间

对于初学者来说,学习编程最害怕的就是,

那么,Typescript 是不是很难?

首先,我可以肯定地告诉你,你的焦虑是多余的。新手对学习新技术有很强的排斥心理,主要是因为基础不够扎实,然后自信心不够强。

1.infer关键字

  • infer关键字
  • 条件类型提供了一个infer关键字, 可以让我们在条件类型中定义新的类型
// 需求: 定义一个类型, 如果传入的是数组, 就返回数组的元素类型,
//                     如果传入的是普通类型, 则直接返回这个类型

// type MyType<T> = T extends any[] ? T[number] : T;
// type res = MyType<string[]>;
// type res = MyType<number>;

// type MyType<T> = T extends Array<infer U> ? U : T;
// type res = MyType<string[]>;
// type res = MyType<number>;

2. unknown

/*
 1.什么是unknown类型?
 unknown类型是TS3.0中新增的一个顶级类型, 被称作安全的any
* */
* 
// 1.任何类型都可以赋值给unknown类型
// let value:unknown;
// value = 123;
// value = "abc";
// value = false;

// 2.如果没有类型断言或基于控制流的类型细化, 那么不能将unknown类型赋值给其它类型

// let value1:unknown = 123;
// let value2:number;
// value2 = value1;
// value2 = value1 as number;
// if(typeof value1 === 'number'){
//     value2 = value1;
// }

// 3.如果没有类型断言或基于控制流的类型细化, 那么不能在unknown类型上进行任何操作

// let value1:unknown = 123;
// value1++;
// (value1 as number)++;
// if(typeof value1 === 'number'){
//      value1++;
// }

// 4.只能对unknown类型进行 相等或不等操作, 不能进行其它操作(因为其他操作没有意义)

// let value1:unknown = 123;
// let value2:unknown = 123;
// console.log(value1 === value2);
// console.log(value1 !== value2);
// console.log(value1 >= value2); // 虽然没有报错, 但是不推荐, 如果想报错提示, 可以打开严格模式

// 5.unknown与其它任何类型组成的交叉类型最后都是其它类型

// type MyType = number & unknown;
// type MyType = unknown & string;

// 6.unknown除了与any以外, 与其它任何类型组成的联合类型最后都是unknown类型

// type MyType = unknown | any;
// type MyType = unknown | number;
// type MyType = unknown | string | boolean;

// 7.never类型是unknown类型的子类型
// type MyType = never extends unknown ? true : false;

// 8.keyof unknown等于never
// type MyType = keyof unknown;

// 9.unknown类型的值不能访问其属性,方法,创建实例
// class Person {
//     name:string = 'lnj';
//     say():void{
//         console.log(`name = ${this.name}`);
//     }
// }
// let p:unknown = new Person();
// p.say();
// console.log(p.name);


// 10.使用映射类型时, 如果遍历的是unknown类型, 那么不会映射任何属性
// type MyType<T> = {
//     [P in keyof T]:any
// }
// type res = MyType<unknown>

3. 迭代器和生成器

/*
和ES6迭代器一样
for...of
从零玩转JavaScript核心+新特性③
140-JavaScript-数组高级API上(掌握)
从零玩转JS新特性+流行框架⑥
34-Iterator接口(掌握)
35-Iterator接口应用场景(掌握)
* */
let someArray = [1, "string", false];
for (let entry of someArray) {
    console.log(entry); // 1, "string", false
}
/*
生成器
当生成目标为ES5或ES3,迭代器只允许在Array类型上使用。
在非数组值上使用 for..of语句会得到一个错误,
就算这些非数组值已经实现了Symbol.iterator属性。
为了解决这个问题, 编译器会生成一个简单的for循环做为for..of循环
* */

4. 映射类型

/*
1.什么是映射类型?
根据旧的类型创建出新的类型, 我们称之为映射类型
* */

interface TestInterface1{
    name:string,
    age:number
}
interface TestInterface2 {
    readonly name:string,
    readonly age:number
}
*/
interface TestInterface1{
    name:string,
    age:number
}
interface TestInterface2{
    readonly name?:string,
    readonly age?:number
}
type ReadonlyTestInterface<T> = {
    // [P in keyof T]作用: 遍历出指定类型所有的key, 添加到当前对象上
    // readonly [P in keyof T]: T[P]
    // readonly [P in keyof T]?: T[P]
    -readonly [P in keyof T]-?: T[P]
}
type MyType = ReadonlyTestInterface<TestInterface2>


// 我们可以通过+/-来指定添加还是删除 只读和可选修饰符


// 由于生成只读属性和可选属性比较常用, 所以TS内部已经给我们提供了现成的实现
// Readonly / Partial

type MyType2 = Readonly<TestInterface1>
type MyType3 = Partial<TestInterface1>
type MyType4 = Partial<Readonly<TestInterface1>

5. 模块系统

1.ES6模块
1.1分开导入导出
export xxx;
import {xxx} from "path";

1.2一次性导入导出
export {xxx, yyy, zzz};
import {xxx, yyy, zzz} from "path";

1.3默认导入导出
export default xxx;
import xxx from "path";
*/
/*
2.Node模块
1.1通过exports.xxx = xxx导出
通过const xxx = require("path");导入
通过const {xx, xx} = require("path");导入

1.2通过module.exports.xxx = xxx导出
通过const xxx = require("path");导入
通过const {xx, xx} = require("path");导入
* */
/*
ES6的模块和Node的模块是不兼容的, 所以TS为了兼容两者就推出了
export = xxx;
import xxx = require('path');
* */
import obj = require("./55/test");
console.log(obj);

6. 命名空间


/*
1.什么是命名空间?
命名空间可以看做是一个微型模块,
当我们先把相关的业务代码写在一起, 又不想污染全局空间的时候, 我们就可以使用命名空间
本质就是定义一个大对象, 把变量/方法/类/接口...的都放里面

2.命名空间和模块区别
在程序内部使用的代码, 可以使用命名空间封装和防止全局污染
在程序内部外部使用的代码, 可以使用模块封装和防止全局污染
总结: 由于模块也能实现相同的功能, 所以大部分情况下用模块即可
* */
// namespace Validation {
//     const lettersRegexp = /^[A-Za-z]+$/;
//     export const LettersValidator  = (value) =>{
//         return lettersRegexp.test(value);
//     }
// }

/// <reference path="./56/test.ts" />
console.log(Validation.LettersValidator('abc'));
console.log(Validation.LettersValidator(123));
  • test.js
var Validation;
(function (Validation) {
    var lettersRegexp = /^[A-Za-z]+$/;
    Validation.LettersValidator = function (value) {
        return lettersRegexp.test(value);
    };
})(Validation || (Validation = {}));
/*
1.什么是命名空间?
命名空间可以看做是一个微型模块,
当我们先把相关的业务代码写在一起, 又不想污染全局空间的时候, 我们就可以使用命名空间
本质就是定义一个大对象, 把变量/方法/类/接口...的都放里面

2.命名空间和模块区别
在程序内部使用的代码, 可以使用命名空间封装和防止全局污染
在程序内部外部使用的代码, 可以使用模块封装和防止全局污染
总结: 由于模块也能实现相同的功能, 所以大部分情况下用模块即可
* */
// namespace Validation {
//     const lettersRegexp = /^[A-Za-z]+$/;
//     export const LettersValidator  = (value) =>{
//         return lettersRegexp.test(value);
//     }
// }
/// <reference path="./56/test.ts" />
console.log(Validation.LettersValidator('abc'));
console.log(Validation.LettersValidator(123));

码字不易,在线求个三连支持。

大家记得收藏前,先点个赞哦!好的文章值得被更多人看到。

推荐阅读:

13万字C语言保姆级教程2021版

10万字Go语言保姆级教程

2 万字 Jquery 入门教程

3 万字 html +css 入门教程

169集保姆级C语言视频

最后,再多一句,粉丝顺口溜,关注江哥不迷路,带你编程上高速。

版权所有,请勿转载,转载请联系本人授权


点击全文阅读


本文链接:http://zhangshiyu.com/post/26003.html

类型  模块  命名  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1