良好编码习惯养成助手——TS
js简单易上手灵活多变,既是优点,也是缺点,会为上线的代码埋下隐患,简单举“栗”子:
let a;
a = 10;
a = '这是新值';
在js中这样书写是不会报错的,因为js不会对函数的参数类型和个数进行检测,但在项目中如果我们所需的值仅只为数字进行运算如下:
function sum(a, b){return a + b;
}
console.log(sum(12, 34)) // 46
console.log(sum(12, '34')) // 1234
显然无论我们传数字还是字符串,编辑和测试都不会出现编译错误,但是返回的数据结果却大不一样,这就导致我们在开发大型项目的过程中维护起来非常的头痛。而TS就是在js的基础上增加了类型的判断,所以一切支持js的地方都可以用ts,但值得注意的是,ts是不可直接被解析的,需要转换成js后才可以被解析。可能会有同学问为什么不直接整一套可解析的ts,是因为js就目前而言是不可代替的一门开发语言,在短时间之内添加一套辅助工具是最为这种的办法,也是为了兼容习惯了js的老程序猿。目前而言,ts不是必要的,但近几年一定会全面推广,所以快点学起来吧!
首先我们在正式使用ts之前,需要先配置好环境,如图:
首先我们先来认识一下TS基础类型
- any => 任意类型,相当于放弃了类型校验,没有了ts的使用意义,不推荐使用
- number => 数字类型
- string => 字符串类型,包括字符串和模板字符串
- boolean => 布尔类型,true 、false
- [] => 数组类型(number[]、string[]、泛型: Array、Array)
- [string,number,boolean] => 元组类型,必须一一对应
- enum => 枚举类型
- void => 表示方法返回空
- null => 表示值缺失,空对象引用
- undefined => 未定义
- never => 其它类型,代表从不会出现的值
let a: number; // 当a的类型被设定为数字之后,那么a的值便只能是数字类型
a = 10;
// a = '字符串类型值'; // 此时a会报错
let a: string = '字符串类型值'; // 声明完变量直接对其进行赋值
let b = false; // 如果变量的声明和赋值是同步的,TS可以自动对变量的类型进行检测
// b = 123; // 此时b会报错,上方类型默认为b: boolean;
在书写方面呢,就像c++语言里的字面量方式,也可以给一个变量以多种类型,专业点讲叫联合类型,具体如下:
// 字面量赋值方式(字面量方式更类似于常量,只能赋值一次)
let a: 10;
a = 10;
// a = 11; // 此时a会报错,只能被赋值以10let b: 'male' | 'female';
b = 'male'
b = 'female'
// 同理可得 =>
let c: number | boolean; // 联合类型
c = 123;
c = false;
如果当我们没有给变量声明类型时,就会有隐式类型any,由于any类型想当与放弃了类型校验,所以既然我们要用ts,就最好不要用any类型。
let a = 10;
// a = '字符串类型值'; // 自动校验a的类型为number
let b;
b = false;
b = 123;
b = '345'; // 自动校验b的类型为any(隐式类型any)
但是如果我这里有一个变量我也不知道未来会具体给他什么样的值,那就用unknown,我们可以对比来看一下:
let a: string;
let b: any;
let c: unknown;
// any与unknown均可以赋值任意类型都不会报错,但他们的区别就在于any赋值给已有类型的变量不会报错,而unknown会作为一种未知类型而被限制
a = b;
c = b;
// a = c; // 因为a为string,c为unknown而类型校验不通过
b = 122 | '345' | false; // 各种类型赋值均不报错
c = 122 | '345' | false; // 各种类型赋值均不报错// unknown实际上是一个类型安全的any,不能直接赋值给其它变量,如果要赋值,则需先类型一致
// 方法一:
if(typeof c === "string") {a = c
}
// 方法二:类型断言
a = c as string; // 断言的两种书写方式
a = <string>c;
接下来,我们说一下函数的类型:
// 返回数字类型
function fun(): number {return 123;
}
// 返回多种类型
function fun(a: boolean): string | number {if(a) {return 521;} else{return '你失去了我';}
}
fun(true);
// 返回空类型
function fun(): void {console.log('浩浩爱茜茜');// return ;// return undefined;// return null;
}
// 没有返回值,报错的时候
function fun(): never{throw new Error('这里有一个错误');
}
说完了函数返回值我们再来说一下函数的参数:
// 设置函数结构的类型声明 (参数:类型)=> 返回值类型
let f = (a:number,b:number)=> number;
f = function fun(c1:number,c2:number): number{return 10;
}
有一种我们不会用到的类型那就是object,为什么这么说呢,在我们的js当中呢,花括号是一个对象,函数是一个对象…万物皆对象,所以在实际应用中,object并不会用到:
let a = {}; // 声明a是一个对象类型,并且可以指定对象中有哪些属性
let b = {name: string, age: number};
b = {name: '茜茜',age: 3};
// b = {naem: '浩浩', age: 3, mex: '男'}; // 属性只能一一对应
// 可以通过加?将属性变为非必要属性
let c = {name: string, age: number, mex?: string};
c = {name: '茜茜',age: 3};
c = {name: '浩浩', age: 3, mex: '男'}// 在开发过程中呢还可能存在的情况是对象中的属性是未知的,比如参数的不确定性,数量不确定,类型不确定,这种情况下则需要添加[propName: string]: any
let d = {name: string, [propName: string]: any}; // propName是自定义的,非固定
d = {name: '茜茜'};
d = {name: '浩浩', age: 3, mex: '男', text:'我的老婆是茜茜'}
// d = {age: 9, mex: '女', text:'我是无名氏'} // 缺少了必要属性name,所以报错
说完了对象,那就不得不说一下数组,上干货:
// 类型[] 或者 Array<类型>
let arr = number[];
arr = [1,2,3]
let arr1 = string[];
arr1 = ['1','2','3']
// tuple 元组 固定长度的数组
let arr2 = [string,string,number]
arr2 = ['1','2',3]
类似元组,我们再来看下枚举:
// enum 枚举 常用于选择范围有限的内容
enum Gender{male = 0, // 0->男female = 1 // 1->女
}
let i = {name: string,sex: Gender}; // 性别 男|女
i = {name: '茜茜',sex: Gender.female
}
console.log(i.sex === Gender.female) // true
上面我们有说到"|"的用法,那么现在来说一下’&'的使用:
// 在react语法中呢, || 表示或 && 表示与 对应的在ts中用单一的 | + &
// let a: string & number // 实质上这种写法是不存在的,因为没有哪一种类型可以既是字符串又是数字
let obj: {name: string} & {age: number};
// obj = {name: '浩浩'} // 因为&表示同时满足所以单写一个属性会报错
obj = {name: '浩浩', age: 3}
// 那为什么不直接写let obj: {name: string,age:number}呢?这个&看上去似乎是多此一举,但是在大型的项目开发中会存在这种场景,两组数据有公共的部分,但是数据b包含了数据a的全部属性,这种情况下,我们就可以通过这种方式对已声明的a类型进行补充后使用
现在,我们来说下类型的别名使用:
// 我们要使用到type关键字
type myType = 1 | 2 | 3 | 4 | 5;
let a: myType
let b: myType
//b = 6 //因为myType里不包含6所以会报错
//类型别名呢,就相当于是一个类型的“公共组件”,用于声明公共的类型,可多处复用
与别名相类似的呢,还有接口:
// 接口主要是用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
// 同时也可以当成类型声明去使用
// -> interface
type myType{ // 描述一个对象的类型name: string,age: number
}
// type myType{ // 用type来声明对象类型如果重名是会报错的
// sex: string,
// }
interface myInterface {name: string,age: number
}
interface myInterface { // 而接口是可以重名定义sex: string
}
let obj={ // 此时数据内容必须满足以上接口定义的全部结构name: '茜茜',age: 3,sex: '女'
}// 接口可以在定义类的时候去限制类的结构
// 接口中所有的属性不能有实际的值,只定义对象而不考虑实际值
// 接口中所有的方法都是抽象方法,定义类时去实现一个接口的要求规范interface myInter{name: string,fun(): void
}
class MyClass implements myInter{name: string;constructor(name:string){this.name = name;}fun(){console.log('这里是一个函数')}
}
对象的属性可以被任意修改,这导致了数据的不安全系数增高,例如:age:-38,人的年龄是不会出现负数,为了避免这种情况,就需要用到属性封装,这其中包含了ts的修饰符的知识点:
// public 修饰的属性可以在任意位置访问或修改 默认值 (你爸的钱,你可以继承花销,你儿子,你孙子都可以)
// private 私有属性,私有属性只能在类内部使用或修改(你爸的媳妇,你不能叫媳妇)但是可以通过添加方法使得私有属性可以被外部访问(但你可以叫妈)
// protected 受保护的属性,只能在当前类和子类中访问或修改,实例中不可以访问(基因里面的东西无法通过外界来更改,只有基因内部的突变)class Person{name: string;age: number;constructor(name:string,age:number){private this._name=name;private this._age=age;}//TS中属性存储器get name(){return this._name;}set name(val: string){this._name=val;}get age(){return this.age;}set age(val: string){if(val>=0){ // 通过函数方法来改变就可以增加对数据的限制this._age=val;}else {console.log('输入错误,请重新输入')}}
}
const pre=new Person(name:'浩浩',age: 4)
pre.age = 3
console.log(pre) // {name:'浩浩',age:3}
最后,我们来说一说泛型:
// 在定义函数或类时,会遇到类型不明确就可以使用泛型
function fun<T>(a:T):T{return a;
}
// 可以直接调用具有泛型的函数
let r=fun(10)// 不指定泛型,ts可以自动对类型进行推断
let r2=fun<string>('这是一串字符串') // 指定泛型// 泛型可以同时指定多个
function fun2<T,K>(a:T, b:K):T{console.log(b);return a;
}
fun2<number,string>(123,'345')// 泛型加接口约束
interface Inter{length: number;
}
function fun3<T extends Inter>(a:T): number{return a.length
}
class myClass<T>{name:T;constructor(name:T){this.name= name}
}
const MC = new myClass<string>('123')
基础内容告一段落,我们在这里说一下ts的编译指令
由于ts无法在浏览器里解析,所以我们没回书写完ts代码需要用tsc 文件名.ts
进行内容的转js,这就使得非常繁琐枯燥,为了更直观的查看我们编写的效果,可以使用tsc 文件名.ts -w
来监听我们ts文件的编译,但只会对当前文件进行监听;这就显得很鸡肋,如果要自动监听全部的ts文件,则需要先使用tsc --init
生成一个tsconfig.json的配置文件,再使用tsc -w
即可监视所有文件
这里我们再说一下tsconfig.json文件内部配置的指令:
// 这里是tsconfig.json文件内部
/*
include用来指定那些ts文件需要被编译 ** -> 任意路径 * -> 任意文件
exclude用来指定那些ts文件不需要被编译 默认值是["node_modules","bower_components","jspm_packages"],仅为默认值时可以直接忽略exclude
*/
{"include": ['./src/**/*','其它任意路径']"exclude":[],"compilerOptions": { //重点 编译器的配置选项"target": "ES3", //ts被编译的es版本 esnext(最新版本)"module": "commonjs", //要使用的模块化规范"lib": [], // 指定项目中要用到的库 eg:["dom"]"outDir": "./", // 指定编译后的文件输出所在目录"outFile": "./", // 将编译后的代码合并到一个文件里 这里要注意的是如果代码里有模块化引入文件的内容需要对module配置对应的规范才能进行正常的编译"allowJs": true, // 是否对js文件进行编译"checkJs": true, // 是否检查js代码符合规范"removeComments": true, // 是否移除注释"noEmit": true, // 不生成编译后的文件"noEmitOnError": true, // 当发生错误时候不生成编译后的文件"strict": true, // 所有严格模式的总开关"alwaysStrict": true, // 用来设置编译后的文件是否采用严格模式"noImplicitAny": true, // 禁止隐式的any类型"noImplicitThis": true, // 禁止不明确类型的this"strictNullChecks": true, // 禁止空值}
}
生成package.json文件使用命令 npm init -y
良好编码习惯养成助手——TS相关推荐
- 良好的编码习惯 —— 5 个提高代码质量的技巧
原文地址:Good Coding Practices – Five Tips to Enhance Code Quality 原文作者:Jay 译文出自:掘金翻译计划 本文永久链接:github.co ...
- 第十四期:5 个 JS 不良编码习惯,你占几个呢?
在阅读JavaScript代码时,你是否有过这种感觉:你几乎不明白代码的作用?代码使用了很多 JavaScript 技巧?命名和编码风格太过随意? 这些都是不良编码习惯的征兆. 在阅读JavaScri ...
- [在线+源码]vue全家桶+Typescript开发一款习惯养成APP
vue-ts-daily 基于Vue.js的2.5.13版本和TypeScript编写的模仿原生应用的WebApp. 源码地址 欢迎star 项目演示地址 建议直接添加到主屏幕(ios端体验差一些). ...
- 习惯养成android软件,六款有助于养成良好习惯的APP(安卓)
原标题:六款有助于养成良好习惯的APP(安卓) 什么是习惯?灬无言理解为不去主动思考就去做的事情,如早起穿衣洗脸刷牙,坐哪路公交,边打开手机听着歌,也不会忘记在什么地方下车,转乘几号线地铁等等. 好习 ...
- 养成不断学习的好习惯_如何使用“小习惯”养成一致的学习习惯。
养成不断学习的好习惯 If there's only one thing I could teach someone before they started learning to program, ...
- 程序员你为什么这么累【续】:编码习惯之日志建议
转自:https://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247484164&idx=1&sn=8351e9fb42e ...
- 出门问问×趁早|内测探索“序列猴子”大模型,联手打造“好习惯小助手”
提到虚拟语音助手,你可能会想到siri--她可以随时随地帮你查地图.定闹钟.找餐厅.打电话.播放歌曲-- 但你有没有想到有一天,语音助手可以进化成"外接大脑"般的存在,ta有丰富多 ...
- 程序员你为什么这么累【续】:编码习惯之工具类规范
导读: 程序员你为什么这么累? 我的编码习惯 - 接口定义 我的编码习惯 - Controller规范 我的编码习惯 - 日志建议 我的编码习惯 - 异常处理 我的编码习惯 - 参数校验和国际化规范 ...
- 我的编码习惯 —— API 接口定义
工作中,少不了要定义各种接口,系统集成要定义接口,前后台掉调用也要定义接口.接口定义一定程度上能反应程序员的编程功底.列举一下工作中我发现大家容易出现的问题: 1. 返回格式不统一 同一个接口,有时候 ...
最新文章
- ubuntu 强制关机后 mysql无法启动
- 大数据时代分析师 Splunk助大数据落地
- Netflix Curator 使用 Zookeeper 编程
- Ajax请求Session超时的解决办法:拦截器 + 封装jquery的post方法
- Mysql bat脚本编写_第一次编写bat脚本
- 关闭(杀死)8080端口
- 字体 素材_4个网站,涵盖几乎所有素材,字体、设计、图片各种资源管够
- 雷达的正交波形设计matlab源码,雷达系统设计MATLAB仿真
- 【BZOJ4710】[JSOI2011]分特产(容斥)
- CF985E Pencils and Boxes
- 国内浏览器双核模式 默认切换chrome内核
- 【Matlab语音识别】声纹识别【含GUI源码 537期】
- 人力资源数据分析师前景_5-数据分析师前景怎么样
- 一个简单的多线程实现
- 免费通信时代何时真正到来?
- Java什么是对象?
- 通过yolov5训练自己的模型中遇到的一些问题及解决办法
- WF(Windows Workflow Foundation)
- LoRa模块网络组成和架构原理是怎样的?
- 在进行IBEACON定位时的可视化处理
热门文章
- 【第26篇】MobileNets:用于移动视觉应用的高效卷积神经网络
- VMware vSphere ESXi 6.7/7.0 定制安装盘(驱动或者SLIC)
- PM必备 | 4种基本素质和8大管理技能
- 华南主板bios怎么恢复出厂设置_最详细的主板bios设置图解教程bios设置指南史无前例...
- 前端对接打印机的一些经验总结
- CSS餐厅小游戏练习1~32关(附答案和链接)
- 不收费的电脑数据恢复软件EasyRecovery16
- android如何获取分屏区域的宽高,Android N获取屏幕高度的问题
- Animate.css动画演示
- blogs博客系统项目介绍