TypeScript
简介
JavaScript是动态类型的语言,其方法参数接收的值可以是任意类型,是不确定的
动态类型意味着
- 运行代码时才知道发生了什么
静态类型意味着
- 在代码运行前,就对它的行为做出预测
TypeScript具备了静态类型检查的优点
TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性,所以 它们都是弱类型
TypeScript代码需要编译为JavaScript代码后才能被浏览器运行
下面就对方法参数的类型进行了限定
function test(obj:string){
}
安装TypeScript编译器
全局安装编译器
npm install -g typescript
编译TypeScript文件
tsc .\Hello.ts
TypeScript类型
类型 | 例子 | |
---|---|---|
字符串类型 | string | |
数字类型 | number | |
布尔类型 | boolean | |
数组类型 | number[],string[],boolean[] … | |
任意类型 | any | 相当于和js一样没有参数类型 |
复杂类型 | type 与 interface | |
函数类型 | () => void | 对函数的参数和返回值进行说明 |
字面量类型 | “a”|”b”|”c” | 限制变量或参数的取值,只能是定义好的三选一 |
nullish类型 | null 与 undefined | |
泛型 | <T>,<T extends 父类型> |
变量声明
let message:string = "Hello,world";
当然这种情况也能省略类型,这种叫做类型推断,会根据赋值情况推断出变量的具体类型
const lowerCaseNames = names.map((e) => e.toLowerCase());
console.log(lowerCaseNames)
标注函数返回值
function add(a:number,b:number) : number{
return a + b;
}
let number = add(3,5);
console.log(number)
这种返回值类型声明也可以省略,交由类型推断去处理
定义对象类型
type Student = {
name:string,
age:number
}
const c1:Student = {name:"小明",age:18};
赋值对象属性必须要和类型定义属性相同
使用interface关键字定义也可以
interface Student2 {
name:string,
age:number
}
typescript中的interface区别于java,主要是用来定义属性的,但也可以定义方法
可选属性
如果定义了可选属性就有可能会在访问时出现undefined的情况
interface Student2 {
name:string,
age?:number
}
typescript类型接收特性:
- 如果一个变量没有明确声明类型,但是和目标类型如果有相同属性,那么也可以被目标类型引用接收
定义对象方法类型
interface Api {
method() : void
}
function test(api:Api){
api.method();
}
test({
method() {
console.log("实现方法");
}
});
传入对象需要实现定义的方法
设置方法参数和返回值类型
let api:Api = {
me(msg: string): string {
console.log(msg);
return msg;
},
method() {
console.log("方法实现");
}
}
api.me("调用方法");
字面量类型规范参数值
function printText(text:string,alignment:"left"|"right"|"center"){
console.log(text,alignment);
}
printText("Hello","center");
使得参数规范,传入的参数需要满足规定好的参数值
Nullish类型接收
使得参数也可以接收null或undefined类型
可接收null需要在后面加
| null
- 但是同时也必须对null值进行判断处理,否则无法通过编译
可接收undefined只需要改为
?:
即可- 但是也需要做判断
或者以上两种都可以用
?.
来判断nullish类型来选择是否执行方法
function printText(text?:string | null){
if (text !== null && text !== undefined){
console.log(text.toUpperCase());
}
console.log(x?.toUpperCase());
}
泛型定义接口
泛型式的定义使得接口不再冗余,使得定义的方式得到了拓展
interface Ref<T> {
value: T
}
const r1 :Ref<string> = {value:"Hello"}
const r2 :Ref<number> = {value:123}
函数泛型定义
function ref<T>(arg:T) : Ref<T>{
return {value:arg};
}
let stringRef = ref("Hello");
stringRef.value.toLowerCase()
这样我们就能获取到其中的string类型属性并调用string类型对应的方法
Class语法
class User {
constructor(name:string) {
this.name = name;
}
name:string
}
let user = new User("张三");
console.log(user.name);
实际上TypeScript中的这种定义类的方法并没有改变JS类的原型继承模式,在编译为JS代码时就能看出
本质上还是原型继承
var User = /** @class */ (function () {
function User(name) {
this.name = name;
}
return User;
}());
var user = new User("张三");
console.log(user.name);
Set和Get方法
- 使用
_name
是为了和方法名区分开来
class User {
constructor(name:string) {
this._name = name;
}
private _name:string
/*只读属性*/
readonly readonlyName:string
/*方法定义*/
work(){
console.log(`${this._name}在工作`)
}
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
}
实现接口
继承也是相同的,和java中类似
interface User {
work()
}
class UserImpl implements User {
constructor(name:string) {
this._name = name;
}
_name:string
/*方法定义*/
work(){
console.log(`${this._name}在工作`);
}
}
//使用接口类型接收对象
let user:User = new UserImpl("张三");
user.work();
如果在实现的子类中需要同时调用接口中定义的方法和来自父类中的方法
需要使用
&
来定义接收类型
let user: User & UserSuperClass = new UserImpl("小明");
类似的也能用super调用父类的方法
使用TypeScript的意义
TypeScript能够帮助我们更好的去理解许多框架源码
使用TypeScript能够使得我们在编程时获得提示,这样子保证了我们代码的安全性
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com