0929 NOTE–TS学习
定义
js的超集,可以在任何浏览器、计算机和操作系统上运行,但是执行时会先编译成js代码执行。
优势
①、有些错误如:未传参,js在浏览器中编译运行时才会报错,而ts在代码执行前便会报错提示
②、代码提示友好程度更高
③、代码中变量的类型声明使语义更清晰易懂
环境搭建
安装ts:
npm i typescript -g / yarn add typescript -g
编译ts文件:
tsc demo.ts //执行后编译生成一个js文件,执行
插件:
npm i ts-node / yarn add ts-node
插件安装后不需要编译啊,直接ts-node demo.ts即可执行
静态类型
给变量声明定义静态类型后,变量类型固定不可修改,变量具有该静态类型的所有属性和方法
基础类型和对象类型
基础类型:
//null , undefined , symbol , boolean , void
const count:number = 123;
const teacherName:string = "john";
对象类型:
const teacher : {
name:string;
age:number;
}
const numbers:number[] = [1,2,3] //数组类型,元素必须为number类型
const getTotal : () => number = () => {
return 666;
}
//函数类型,必须返回一个number类型的结果
类型注解和类型推断
type annotation 类型注解 声明变量时,定义类型,告知TS,该变量类型
type inference 类型推断 声明变量时,不定义类型,TS根据变量值推测变量类型
let count: number = 123;
let cpunt = 123;
注:当确定TS可以分析推断出变量类型时,可以选择类型推断,简化代码,但是当TS无法分析推断出变量类型时,需要类型注解
const firstnum = 1;
const secondnum = 2;
const sum = firstnum + secondnum; //此时可以选择类型推断实现简化代码
function count(firstnum:number, secondnum:number){
return firstnum + secondnum;
}
const sum = count(firstnum , secondnum); //此时需要类型注解,因为TS无法推测传入参数的类型
实际无论类型注解和类型推断,目的都是让变量有一个具体类型
TS的每一个变量以及每一个对象的属性的类型都是固定的
TS函数相关类型
function count(firstnum:number, secondnum:number):number{
//此处第三个注解是为了防止失误导致返回结果与预期不符
//return firstnum + secondnum + '';
return firstnum + secondnum;
}
const sum = count(firstnum , secondnum);
function sayHello():void{ //void类型表示无返回值
console.log("hello")
}
function errorEmitter():never{ //error类型表示该函数永远无法执行完,而是执行部分
throw new Error();
console.log(123);
}
//函数参数解构
//参数传入对象时,在传入时解构
//js
function sum({firstnum,secondnum}){
return firstnum + secondnum;
}
let result = sum({first:1,second:2})
//ts
function sum({firstnum,secondnum}:{firstnum:number,secondnum:number}):number{
return firstnum + secondnum;
}
let result = sum({first:1,second:2})
//箭头函数的两种写法
//传入参数为字符类型,返回结果为数值类型
const func = (str:string) => {
return parseInt(str,10);
}
const func1:(str:string) => number = (str) => {
return parseInt(str,10);
}
函数编写时,入参一般需要类型注解,但是返回值往往可以通过类型推断简写
//当一个变量在初始和后续类型不同时,可以通过同时声明多种类型解决
let count : number | string = 123;
count = "123";
数组与元组
数组
const mixArr: (number | string)[] = [1,2,'3'];
const stringArr : string[] = ['1','2','3'];
const undefinedArr : undefined[] = [undefined];
//类型别名 type alias 便于理解
type User = { name:string;age:number};
const objectArr : User[] = [{
name:'kaige',
age:18
}]
元组
tuple
//数组
const stipulateArr : (string | number)[] = ['kaige',18,'22']
//元组
//约束规定了数组每项对应的类型
//数组的长度,每个元素对应类型固定时,选择元组会更便于管理
const stipulateArr : [string,number,number] = ['kaige',18,22]
Interface接口
定义通用类型
与类型别名的区别:只能代表函数或对象,无法代表基础类型
interface Person{
name:string;
readonly age?:number; //?:语法,表示age属性可有可无,即使传参不具有age属性,也不会报错 readonly只读,不可修改
}
type Person1 = string;
const getPersonName = (person:Person) => {
console.log(person.name)
}
const setPersonName = (person:Person,name:string) => {
person.name = name;
}
注意:当以字面量形式将对象作为参数传入时,一定要符合类型注解,不能有多余属性,否则会报错
interface Person{
name:string;
age?:number;
}
interface newPerson{
name:string;
age?:number;
[propName:string]:any; //表示可以存在其他属性,属性名类型为字符,值类型随意
test():string //方法,返回结果为字符类型
}
const person = {
name:'kaige',
gender:'male'
}
const getPersonName = (person:Person) => {
console.log(person.name)
}
getPersonName(person); //不报错
getPersonName({
name:'kaige',
gender:'male'
}); //报错 对象字面量传参会进行强校验
//class应用接口
class User implements Person{
name = "kaige";
test(){
return 'aaa'
}
}
//接口定义函数类型
interface test{
():void
} //无参无返回值的函数
let kg : test = () => {
console.log('kaige');
}
kg();
接口interface实际只是TS帮助做语法校验的工具,在编译转化成js代码时,interface的语句会被剔除
类
类的定义与继承
class Person {
name = 'kaige';
getName(){
return this.name;
}
}
const person = new Person();
console.log(person.getName());
super的常用:在子类重写父类方法后,可以通过super调用父类的该方法
类中的访问类型和构造器
//三种访问类型:private protected public
//public 允许在类的内外被调用
//private 允许在类内被调用
//protected 允许在类内及继承的子类中使用
//constructor
class Person {
constructor(public name:string){}
}
//等价于
class Person {
public name:string;
constructor(public name:string){
this.name = name
}
}
//ts中,调用父类的构造函数时,如果父类的构造函数需要传入参数,还要按照父类构造函数的类型注解规则传入参数,否则会报错
class Teacher {
constructor(public name : string){}
}
class Student extends Teacher {
constructor(public age : number){
super('kaige')
}
}
let kg = new Student(22);
console.log(kg.name,kg.age)
类的getter和setter
//作用:调用私有属性,给类的私有属性加密保护
//单例模式
class Parent {
private static kaige:Parent; //私有化静态属性kaige,Parent类型,只能类内部调用
private constructor(public name : string){}; //私有化构造函数,无法通过new创建新实例
static newParent(){ //静态方法newParent,只能类本身调用
if(!this.kaige) this.kaige = new Parent('kaige');
return this.kaige;
} //属性挂载在类身上,实现类似构建新实例对象的效果
}
let child1 = Parent.newParent();
let child2 = Parent.newParent();
console.log(child1.name,child2.name) //kaige kaige
console.log(child1 === child2); //true
//单例模式,获取的是同一个实例对象kaige,第一个实例对象kaige是new构造的
抽象类
//抽象类只能被继承,不能被实例化
//将共用性的属性、方法抽离成类进行封装
abstract class Graph{
abstract getArea() : number
}
class Circle extends Graph{
getArea(){
return 123;
}
}
class Triangle extends Graph{
getArea(){
return 123;
}
}
class Square extends Graph{
getArea(){
return 123;
}
}
interface Teacher {
name:string;
}
interface Student extends Teacher {
age : number;
}
interface People extends Teacher {
gender : string;
}
let teacher = {
name : 'wanggang',
}
let student = {
name : 'kaige',
number : 18,
}
let people = {
name : 'xiaopang',
gender : "male"
}
function getName(User : Teacher | Student | People){
console.log(User.name)
}
//简写
function outputName(User : Teacher){
console.log(User.name)
}
getName(teacher);
getName(student);
getName(people);
outputName(teacher);
outputName(student);
outputName(people);
|