一、简介
1、TS是什么?
以JS为基础构建的语言,一个JS的超集。
可以在任何支持JS的平台中执行;
TS扩展了JS,并添加了类型;
TS不能被JS解析器直接执行,需要将TS编译为JS;
2、TS增加了什么
增加了类型、支持ES新特性、添加了ES不具备的新特性、配置选项。
二、环境搭建
1、安装Node.js
2、安装TS:npm i -g typescript
3、创建一个TS文件
4、使用TSC对TS文件进行编译:tsc xxx.ts
三、基本类型
1、声明
通过类型声明可以指定TS变量(参数、形参)的类型。
指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明。
声明方式:let xxx:类型;
let xxx:类型=值;
function fun(参数名1:类型,参数名2:类型):返回类型 { ... }
自动类型判断:当对变量的声明和赋值同时进行时,TS编译器会自动判断变量的类型
如果变量的声明和赋值同时进行,可以省略类型声明。
2、类型
类型 | 例子 | 描述 |
---|---|---|
number | 正数、负数、小数 | 任意数字 |
String | 'h',"h",gh | 任意字符串 |
Boolean | true、false | 布尔值 |
字面量 | 其本身 | 限制变量的值就是改字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的any |
void | 空值(undefined) | 没有值或者undefined |
never | 没有值 | 不能是任何值 |
object | {name:"xxx"} | 任意的JS对象 |
array | [1,2,3] | 任意JS数组 |
tuple | [6,5] | 元素、TS新增类型,固定长度数组 |
enum | enum{A,B} | 枚举,TS中新增类型 |
字面量
可以给对象赋值一个固定的值,可以通过 | 来赋值多个值或多中类型
|------------------------|-------------------|
| let a:10 | a的值只能是10 |
| let b:10 | "aabc" | b的值只能是10或者字符串aabc |
| let c:number | string | c的值只能是数字或者字符串 |
any
可以是任何值(一般不用)
把这两个变量赋值给其他变量
两种定义方式:let a:any (显示) let b (隐式)
|-----------|-------------------|
| let a:any | a="1";a=1;a=false |
| let b | b="1";b=1;b=false |
unknown
可以是任何值(安全的any)。
|---------------|-------------------|
| let a:unkonwn | a="a";a=1;a=false |
any与unknow的区别:
TypeScript
let s:string s="1";
let a:any a=1;
let b:unknown b="1";
s=a(不报错)
s=b(报错)
强制转换unknown
TypeScript
//方式1
if(typeof b==='string'){s=b}
//方式2
s=e as string;
void
TypeScript
//返回null或者undefined(不用return)
function fu():void{}
//null或者undefined都不返回
function fu():never{ throw new error('报错')}
Object
表示一个JS对象;
let a:object; a={}; a=function(){}
{}用来指定对象中可以包含那些属性。
语法:{属性名:属性值,属性名:属性值......属性名(不是必须的)?:属性值}
在属性后面写?,表示这个属性可写可不写。
TypeScript
Let b:{name:string}
b={name:"xxxx"}
Let c:{name:string,age?:number}
c={name:"xx"}
c={name:"xxx",age:1}
随意数量的属性名:{属性名:值,[变量名:string:any]};
TypeScript
//abc代表任意类型的属性
Let b:{name:string,[abc:string]:unknown}
b={name:"xxx",c:"xx",d:false}
b={name:"xxx"}
当对象为函数时。其中a、b参数已定义为number所以在function中的参数和返回值
需要定义时的一致,在function中进行显示的定义类型也不行。
TypeScript
Let d:(a:number,b:number)=>number;
d=function(n,m){return n+m}
Array
声明方式:类型[]、array<类型>
TypeScript
Let a:string[];
Let b:number[];
Let c:array<String>
Tuple
长度固定的数组。
声明方式:Let xxx:[ 类型1,类型2,...]
Enum
枚举:enum类名{ 变量名=值,变量名=值,.......}
使用:类名.变量名
其他注意
&表示同时
Let a:{name:string}&{age:number};
a中的属性需要name和age同时出现。
类的别名
Type mytype=1 | 2 | 3 | 4;
Let a:mytype;
a的值可以是mytype中的任何值。
四、编译选项
1、自动编译文件
编译文件时,使用-w指令后,TS编译器会自动监视文件中的变化,并在文件发生变化时对文件重新编译。
TypeScript
tsc xxx.ts -w
2、自动编译整个项目
直接使用TSC命令,可以自动将当前项目下的所有TS文件编译为JS文件。
步骤:在当前目录创建一个tsconfig.json
在这个文件中配置:include、exclude等配置。
include:定义希望被编译文件所在目录。
include:["路径","***"]
**:表示当前路径所有文件、文件路径。
*:表示当前路径所有文件。
exclude:定义需要被排除的文件目录
exclude:["",""]
extend:定义被继承的配置文件。
extend:["",""]
files:指定被编译文件的列表。
files:["xxx.ts","aaa.ts"]
CompilerOptions:编译器的选项,使用JSON配置。
target:编译成JS的版本。
"target":"ES6" (ES3、5、6、2015、16、17、18......)
module:指定要使用的模块化的规范。
"module":"none" (none、system、amd......)
lib:用来指定项目中要使用的库
"lib":"es5" (ES5 ES6 ES2015)
outDir:用来指定编译后文件的所在目录
"outDir":"./dist"
allowJs:是否编译JS,默认否。
"allowJs":false
checkJs:是否检查JS代码,默认false。
"checkJs":false
removeComments:是否移除注释。
"removeComments":false
noEmit:不生成编译后的文件。
"noEmit":true
NoEmitOnError:当生成时有错误。就不生成。
"NoEmitOnError":false
语法检查相关的配置:还是在CompilerOptions下配置。
alwaysStrict:开启严格模式,默认false,当有引入和export操作时默认开启。
"alwaysStrict":false
noImplicitAny:检查隐式的any
"noImplicitAny":true
noImplicitThis:不允许不明确类型的this。
"noImplicitThis":true
strictNullChecks:检查空值,在变量可能为空时报错。
"strictNullChecks":true
strict:严格检查的总开关。开启以上的语法相关检查。
"strict":false
五、面向对象
1、类简介
类就是对象的模型,程序中可以根据类创建指定类型的对象。
创建一个对象:class 对象名{......}
创建一个属性:属性名:类型=值;
创建一个静态属性:static 属性名:类型=值;
创建一个只读属性:readonly 属性名:类型=值;
创建一个只读静态属性:static readonly 属性名:类型=值;
创建一个方法:方法名{...方法体...}
创建一个静态方法:static 方法名{...方法体...}
构造函数:构造函数在对象被创建时调用。
写法:constructor( 属性名:类型,属性名:类型)
{this.属性=属性;this.属性=属性}
this代表当前实例对象。
访问非静态的属性或方法:const xx=new 类名(); xxx.属性 xxx.方法名
访问静态的属性或者方法:类名.属性 类型.方法名
TypeScript
class Person{
name:string;
age:number=1;
static a:string="xxx";
readonly b:string="abc";
static readonly c:string="ccc";
printa{
console.log(this.a)
}
static printb{
console.log(this.b)
}
}
let person=new Person();
person.name="abc";
person.printa();
Person.c;
Person.printb()
2、继承
使用继承后,子类将拥有父类中的所有方法和属性。
通过继承可以将多个类中共有的代码写在同一个父类中。
方法重写:如果在子类中添加了父类相同的方法,则子类方法会覆盖父类的方法。
方式:在子类中的子类名后面使用extends父类名来继承父类。
关键字:super。作用调用父类中的方法。
方式:在子类中使用super.父类方法();
TypeScript
class Parent{
name:string;
constructor(name:string){
this.name=name;
}
publicMethod(){
console.log('我是父类方法');
}
}
class ChildOne extends Parent{
one:string;
constructor(name:string,one:string){
super(name);
this.one=one;
}
oneMethod(){
console.log("子类方法")
}
}
class ChildTwo extends Parent{
two:string;
constructor(name:string,two:string){
super(name);
this.two=two;
}
publicMethod(){
console.log("复写了父类的方法")
}
}
3、抽象类
以abstract开头的类是抽象类。
抽象类与其他类区别不大,只是不能用来创建对象。
抽象类就是专门用来继承的类。
抽象类中可以添加抽象方法(没有方法体);
abstract 方法名():返回类型;
TypeScript
abstract class Parent{
name:string;
constructor(name){
this.name=name;
}
abstract publicMethod():string;
}
class ChildOne extends Parent{
age:number;
constructor(name,age){
super(name);
this.age=age;
}
publicMethod(){
console.log("复写父类中的方法")
}
}
4、接口
作用:规范类的属性、方法等。(零件规格一致才能公用)
接口中可以有属性(没有值)、方法(没有方法体);
实现:interface 接口名{}
子类实现:class 类名 implements 接口{}
TypeScript
interface Animal{
name:string;
yell():void;
}
class Cat implements Animal{
name:string;
constructor(name){
this.name=name
}
yell(){
console.log("喵喵喵")
}
}
5、属性的封装
修饰属性的修饰符
public:修饰的属性可以在任意位置访问修改;
Private:私有属性。只能在本类内部进行访问;通过给类添加方法可以是的私有属性能
被访问。
protected:受保护的属性。只能当前类和当前类的子类可以访问此属性。
TypeScript
class Animal{
public _name:string;
protected _age:number;
private _sex:string;
constructor(name:string,age:number,sex:string){
this._name = name;
this._age = age;
this._sex = sex;
}
set sex(value:string){
this._sex = value;
}
get sex(){
return this._sex;
}
}
class Dog extends Animal{
public abc:string;
constructor(name:string,age:number,sex:string,abc:string){
super(name,age,sex);
this.abc=abc
}
}
let dog=new Dog('小黑',2,'男',"xx");
//只能访问下面两个属性
dog._name;
dog.sex;
6、泛型
作用:在类型不明确的时候代替类型使用。
方法:在方法、类中使用大写字母代替。
TypeScript
function method<T>(a:T):T{
return a;
}
function method2<A,T>(a:A,b:T):T{
return b;
}
class Person<T>{
name:T;
constructor( name:T){
this.name = name
}
}
method(1)
method<string>("1")
let perosn=new Person<string>('zhangsan')