准备工作:
环境安装:npm install -g typescript
查看:tsc-v
出现版本号说明安装成功
安装VScode编辑器:https://code.visualstudio.com/
为什么选择VSCode?ts与vscode都为微软家产品,支持比较好。
开始学习
安装ts-node
模块:npm install -D ts-node
此模块可以减去ts的编译阶段,不用使用tsc demo.ts
将ts编译为.js
结尾的js文件,而是直接使用ts-node demo.ts
直接进行调试。https://blog.csdn.net/themagickeyjianan/article/details/94003538
基础语法:
静态类型:number string boolean null undefined symbol void 可以直观的判断变量或对象的属性和内容是什么
const num :number = 10;
const name :string = "lisa"
对象类型:
const teacher: {
name: string;
age: number;
} = {
name: 'lisa',
age: 29,
};
const numbers: number[] = [1, 2, 3];
class Person {}
const person: Person = new Person();
ts中的类型可以很方便的给予代码提示。
两个概念:
type annotation 类型注解 开发者定义变量类型
type inference 类型推断 ts自动分析变量类型
在ts中最主要功能之一的就是类型校验,在ts开发中尽量要保持每个变量都有已知的类型,手动给变量定义类型就属于类型注解,ts是可以自动推断类型的,自动推断类型就属于类型推断。
const num:number = 12 //类型注解
const doubleNum = num * 2 //类型推断
一般在函数参数中都需要进行类型注解:
function getTotal (num1:number, num2:number) { //类型注解
return num1 + num2
}
const total = getTotal(1, 2); //类型推断
函数返回值类型:void never
声明一个void类型的变量只能为其赋值null或undefined
function sayHello():void{ // void表示函数没有返回值
console.log('hello')
}
never类型表示的是那些永不存在的值的类型。 例如,never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是never类型,当它们被永不为真的类型保护所约束时。
function EmitError():never{
throw new Error('error')
}
function Infinite():never{
while(true){
}
}
函数参数解构:
function deconstruction({name,age}:{name:string,age:number}) :string{
return `${name}今年${age}岁了`
}
deconstruction({name:'lisa',age:15})
函数参数解构需要想如上函数入参时,进行类型声明
函数定义类型:
const fn = (str:string):number => {
return parseInt(str, 10)
}
const fn1: (str : string) => number = (str) => {
return parseInt(str, 10)
}
一个变量多个类型:
let temp:number | string = 123;
temp = 'lisa';
数组:
const numArr:number[] = [1, 2, 3];
const strArr:string[] = ['a', 'b', 'c'];
const arr:(number | string)[] = ['s', 1, 2, 'aa']; // 数组中多种类型
元组:tuple
let tupleArray:[string, number, string] = ['lisa', 12, 'rice'];
元组可以理解成长度固定,每一项类型固定的数组。
接口:interface
interface Person {
name:string;
age?:number;
readonly sex:string;
[propName:string]:any;
say():string
}
上述接口含义是 name是必选,age可选 sex只可读不可写,[propName:string]:any表示任意属性,say()表示方法属性,返回值为string
例子:
interface Teacher extends Person{ // 接口继承
teach():string
}
const getName = (person:Teacher):void => {
console.log(person.name, person.sex,person.son)
}
const setName = (person:Person,name:string):void => {
person.name = name
}
let dadada = {
name:'',
age:2,
sex:'male',
son:'tom',
say(){
return 'dadada'
},
teach(){
return 'teach'
}
}
setName(dadada,'lisa')
getName(dadada)
类去应用一个接口:implements
interface Person {
name:string;
age?:number;
[propName:string]:any; // 任意类型
say():string;
}
class Lucy implements Person{
constructor(){
}
name = 'sss'
say(){
return 'xsxsxs';
}
}
const lucy = new Lucy();
console.log(lucy); // {name: 'sss'}
ts中的类:
class Person {
name="lisa";
sayName(){
return this.name
}
}
class Student extends Person{
constructor(){
super()
this.name = 'jack'
}
sayName(){
return super.sayName() + '-lisa'
}
}
let student = new Student();
student.sayName(); // jack-lisa
在ES6中当子类中的方法覆盖了父类中的方法,但还需要去使用父类的方法,那么就可以使用super去调用
类中的访问类型和构造器:
private:只在当前类中可以使用,不可被继承,不可在子类中访问,子类也不可声明同名属性,实例中也不存在该属性(一句话:只能在当前类的内部访问)
protected:与private有一点区别:1.可以在子类中访问,2.不能在实例中访问,但是可以在枚举。
static:这些属性存在于类本身,而不是类的实例,只能通过类名访问该属性,即使在该类之内也要加上类的名称。可以被子类继承
public:默认不写,在当前类中可使用,可以在实例中访问,也可被子类继承。
构造器新写法:
class Person{
constructor(public name:string){}
}
构造器旧写法:
class Person{
name:string
constructor(name:string){
this.name = name;
}
}
看一个继承:
class Student extends Person{
constructor(public age:number, name:string){
super(name)
}
}
let student = new Student(12,'lisa');
console.log(student.name, student.age);
单例模式:
class SingleTon {
static instance: SingleTon
createInstance(){
if(!this.instance){
return this.instance = new SingleTon()
}
return this.instance
}
}
let ins1 = SingleTon.createInstance();
let ins2 = SingleTon.createInstance();
console.log(ins1 === ins2) // true
枚举:
enum 枚举类型用于定义数值集合
enum Status {
Html,
CSS,
JavaScript
}
console.log(Status.CSS); // 1
如果对enum中的元素赋值:
enum Status {
Html,
CSS = 3,
JavaScript
}
console.log(Status.Html); // 0
console.log(Status.CSS); // 3
console.log(Status.Html); // 4
泛型(generic):
为了对不确定数据类型进行统一定义那么需要使用泛型
比如
function fn(params:string):string{
return params;
}
fn函数传入一个字符串返回一个字符串,如果要求传入一个数字返回一个数字那么就需要再写一个函数。使用泛型可以解决这个问题。
function fn<T>(params:T) :T{
return params;
}
函数在执行的时候可以传入类型,来定义需要的类型。
function fn<T>(params:T) :T{
return params;
}
fn<string>("qwer");
类中的泛型:
class Data<T>{
constructor(private data:T[]){}
getItem(index){
return this.data[index]
}
}
泛型继承
interface Item{
name:string
}
class Data<T extends Item>{
constructor(private data:T[]){}
getItem(index:number){
return this.data[index].name
}
}
let a = new Data([{name:"s"}])
console.log(a.getItem(0));
泛型还可以继承基础类型
class Data<T extends number | string>{
constructor(private data:T[]){}
getItem(index:number){
return this.data[index]
}
}
let a = new Data([1,2,"sss"])
console.log(a.getItem(0));
命名空间(namespace):
使用命名空间可以解决命名冲突问题
使用语法:
namespace Components{
class aaa {}
let obj = {}
}
如果一个命名空间中的变量需要在外部被访问,那么还需要将它export出去
namespace Components{
export class aaa {}
let obj = {}
}
要在另外一个命名空间中使用Components.aaa
待续。。。
网友评论