一、TS开发环境搭建
1.下载安装node
2.使用npm指令全局安装ts
进入命令行
输入:npm i -g typescript
3.创建ts文件 4.使用tsc对ts文件进行编译
进入命令行
进入ts文件所在目录
执行命令:tsc xxx.ts
二、TS的类型声明
let a:number;
a = 1
function sum(b:number, c:number):number{
return b+c;
}
let result = sum(20,30)
先给a指定类型,再赋值。同时函数也是如此;然后再进行编译
三、TS中的类型
//1.可以直接使用字面量来进行类型声明
let a: 10;
a = 10;
a = 20; //这里会报错,因为不可重复赋值
//2.用"|"来表示或,即两个选项都可以,可重复赋值
let b: "男"|"女";
b = "男";
b = "女";
//3.同理可以同时声明两个类型
let c: number|string;
c = true;
c = 'hello';
//4.any表示的是任意类型,一个变量设置类型为any相当于对该变量关闭了TS的类型检测,不建议使用any
let d: any;
d = 1 ;
d = 'zyf';
d = true;
//5.声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any(隐式的any)
let d;
d = 1 ;
d = 'zyf';
d = true;
//6.unknown表示未知类型
let e: unknown;
e = 10;
e = "hello";
e = true;
//7.d的类型是any,它可以赋值给任意变量(专门霍霍别人)
let f:string;
f = d;
//8.e的类型是unknown,它谁都赋值不了(内向),想要赋值的话需要加一个if判断语句
if(typeof e === "string"){
s = e;
}
//9.类型断言,可以用来告诉解析器变量的实际类型
s = e as string;
s = e;
//10.类型断言的另一种写法
s = <string>e;
//11.void用来表示空,以函数为例,就表示没有返回值的函数
function fn(): void{
return
}
function fn(): void{
return undefind;
}
function fn(): void{
return null;
}
//12.never表示永远不会返回结果
function fn2():never{
}
//never一般用来抛出错误
function fn2():never{
throw new Errow('报错了')
}
//13.object表示一个js对象(指定范围太大了,用的比较少)
let a: object
a = {};
a = function(){
}
//常用的是:{},语法:{属性名:属性值,属性名:属性值}
let b: {name:string};
b = {name:'zyf'};
//14.在属性名后面加上?,表示属性是可选的
let b: {name: string, age?: number};
b = {name: 'zyf', age: 18};
let c: {name: string, age?: number};
c = {name: 'zyf'};
//15.[propName: string]:any 表示属性名为任意字符串的属性名,属性名类型为任意类型,任意属性名 个数
let d: {name: string}, [propName: stirng]: any;
d = {name: 'zyf', age: 18, gender:'男', choose: false}
//当外面加了any后,属性名的类型为任意值,如果把any改为string,类型必须是string
//16.设置函数结构的类型声明,语法:(形参:类型, 形参: 类型) => 返回值
let e: (a:number, b: number) => number;
f = function(n1: string, n2: stirng): number{
return 10;
}
//17.string[]和Array<stirng>表示字符串数组,number[]和Array<number>表示数值数组。
let e: string[];
let a: Array<string>
e = ['a', 'b', 'c'];
a = ['a', 'b', 'c'];
let f: number[];
let g: Array<number>;
f = [1,2,3];
g = [1,2,3];
//18.元组,元组就是固定长度的数组,语法:[类型,类型,类型]
let h = [string, number];
h = ['hello', 123]
//必须与声明的一一对应
//19.enum枚举
enum Gender{
Male = 0,
Female = 1
}
let i: {name: string, gender: Gender};
i = {
name: '孙悟空',
gender: 'gender.Male'
}
console.log(i.gender === 1)
//20.&表示同时
let j: { name: stirng }&{ age:number };
j = { name:'zyf', age: 18};
//21.类型的别名,可以直接将myType的值或者类型赋给k和l
type myType = 1 | 2 | 3 | 4;
let k: myType;
let l: myType
四、编译选项
1、当ts文件进行编译时,可以在输出终端末尾加个 -w,这样可以随时监控ts的代码变化,并实时的更新编译后的js文件。如:tsc index.ts -w**
2、上述的方法只能监控一个文件,要是想监控多个文件可以新建个tsconfig.json(里面可以什么都不写),这样想监控多个文件就可以直接tsc -w
3、其中tsconfig.json里面可以添加一些配置
{
/*
tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
"include"用来指定哪些ts文件需要被编译
路径:**符号表示任意目录
*表示任意文件
"exclude"不需要被编译的文件目录
默认值:["node_modules","bower_components","jspm_packages"]
*/
"include":[
"./src/**/*"
],
"exclude":[
"./src/hello/**/*"
]
}
五、类
类的简单应用
class Person{
static name = 'zyf';
age = 18;
readonly sex = 'male'
}
const per = new Person();
//通过实例对象调用类里面的属性
console.log(per.age)
//通过类名来调用里面的属性
console.logr(Person.name)
//报错,因为是静态方法,只能通过类名来调用
console.log(per.name)
//报错,因为sex为只读属性
per.sex = 'female'
构造函数
class Person{
constructor(){
console.log('hello')
}
}
const per = new Person();
每当我们new一个对象时,construetor里的代码就会运行
六、抽象类
/*
以abstract开头的类时抽象类
抽象类和其他类区别不大,只是不能用来创建对象
抽象类就是专门用来被继承的类
*/
abstract class Animal {
name :string;
constructor(name: string) {
this.name = name;
}
/*
定义一个抽象方法
抽象方法使用abstract开头,没有方法体
抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
*/
abstract sayHello() void
}
class Cat extends Animal{
//因为上面定义的是一个抽象方法,所以这里继承的话必须要加上sayHello方法,对其进行重写
sayHello(){
console.log('喵喵喵');
}
}
七、接口
1、接口中的所有属性都不能有实际的值
2、接口只定义对象的解构,而不考虑实际值
3、在接口中所有的方法都只是抽象方法
interface myInter{
name: string;
sayHello(): void;
}
/*
定义类时,可以使类去实现一个接口,
实现接口就是使类满足接口的要求
*/
class MyClass implements myInter{
name: string;
constructor(name: string){
this.name = name
}
sayHello(){
console.log('hello')
}
}
定义接口就相当于定义了一个规范
八、属性的封装
public修饰的属性可以在任意位置访问 (修改),默认是public(不加修饰)
private私有属性,私有属性只能在类内部进行访问
-通过在类中添加方法使得私有属性可以被外部访问
protected受包含的属性,只能在当前类和当前类的子类中进行访问
claa Person{
private name: string
private age: number
constructor(name: string,age: number){
this.name = name
this.age = age
}
setname(val){
this.name = val
}
getname(){
return this.name
}
}
const per = new Person('zyf', 18)
per.setname('ls')
console.log(per.getname())
内部访问:类内部进行访问
外部访问:类外部进行访问,如per.name = 'ls'
九、泛型
function fn<T, K>(a: T, b: K): T{
console.log(b);
return a;
}
fn<number, string>(a: 123, b: 'hello');
interface Inter{
length:number;
}
//T extends Inter表示泛型T必须是Inter实现类(子类)
/*
实现类就是实现接口中约定的内容。
意思是说,接口中定义规范,实现类来确定规范如何运行的。比如接口定义一个Person接口,定义了一个 eat方法,这个吃的方法是空的。
那需要一个实现类比如ZhangSan类实现了Person接口,就必须要给定eat方法的具体实现,说明张三是 如何吃的。
*/
function fn1<T extends Inter>(a: T): number{
return a.length;
}