TypeScript
安装typescript
安装 npm install -g typescript
使用:
运行代码前需要将ts文件编译为js文件
(因为浏览器只能解释运行js代码)
编译ts:
tsc index.ts
生成ts项目目录
(使得vscode可以直接自动编译ts项目)
首先进入ts文件所在文件夹,终端输入
tsc --init
然后生成的tsconfig.json中
解除outdir这一行的注释
可以把 outDir 的 目录 “./” 改为 “./js”
然后点击 Terminal/Run Task
然后选择
tsc watch -tsconfig.json
这样它就会实时把你的ts代码编译为js代码
创建一个html文件以运行js
在html文件里面,输入html,然后点击html:5
添加一行
<script src="js/index.js" ></script>
ts必须指定类型
几种指定类型的方法:
var flag:boolean = true;
var num:number = 123;
var str:string = 'this is a str'
var arr:number[] = [11, 22, 33]
var arr:string[] = ['asd', 'vb ', 'a dasd']
数组类型的指定办法:
var arr:number[] = [11, 22, 33]
var arr:string[] = ['asd', 'vb ', 'a dasd']
或者
var arr:Array<number> = [11,22,33]
元组类型
和数组类型相似,但是可以指定每一个其中的元素的类型
let arr:[number, string] = [123, ‘abc’]
枚举类型
enum Flag {success, error}
(未赋值的话,值等于下标)
enum Flag {success= 1, error = 2}
let f:Flag = Flag.error
也可以这么写
enum Err {‘null’ = -2, ‘undefined’ = -1, ‘success’ = 1}
var e:Err = Err.success
any类型
var tmp:any = true
tmp = ‘abc’
复合类型
var num:number | undefined ;
表示这个变量既可以是undefined 也可以是number类型
var num:undefined
表示这个变量是undefined类型,赋其他任何值都报错
console.log(num) 不会报错
就是说一个变量定义之后,如果不赋值,那么其实就是undefined的状态,这个状态下如果被调用了,比如console.log(num)是会报错的,但如果变量类型定义了undefined,那就不会再报错了
var num:number | null | undefined;
表示这个变量要么是数字类型,要么为空,要么未被赋值
void表示空类型
function run():void {
}
这里表示没有返回值
注意, var b:undefined;那么b只能被 undefined 赋值,同理 null类型也是
never 类型表示不会出现的类型
比如
var b:never = (() => {})
定义匿名函数
var fun2 = function(name:string, age:number):string {
return `${name} --- ${age}`;
}
可选参数,格式为 param ?: type
var fun2 = function(name:string, age?:number):string {
if(age) {
return `${name} --- ${age}`;
}else{
return `${name} --- 未知`;
}
}
和可选参数类似的是,默认参数
格式为 param:type = xxx
var fun2 = function(name:string, age:number=20):string {
return `${name} --- ${age}`;
}
无限参数
function sum(...result:number[]):number {
var sum = 0;
for (var i = 0; i<result.length; i++){
sum +=result[i]
}
return sum
}
sum(1,4,2,1,44,5,6,4)
方法重载
ts中的重载,声明多个重载函数,然后在一个实现中,去判别不同重载,做出不同处理
如果调用时,调用了不存在的重载,比如 getInfo(true) 会报语法错误
毫无疑问这是个愚蠢的设计
箭头函数
setTimeout(()=>{
}, 1000)
其中箭头函数内,this指向上下文
ts引入js包
declare var require: any
const { batchInitPoolNode, get, put } = require('../module/pool');
面向对象,多态,继承
抽象类
abstract class Animal{
abstract eat():any;
}
指定字典变量的类型:
function printLabel(labelinfo: {label:string}):void {
}
即参数必须是一个对象,这个对象的类型是 {label: string}
比如 printLabel({label: “name”})
接口
interface FullName{
firstName:string; 这里用分号
secondName:string;
}
function print( info:FullName ) {
}
那么调用可以这样:
var obj = {
age:13,
firstName:"s",
secondName:"b",
}
print(obj)
可以成功调用,因为obj实现了 FullName接口
但是如果这样:
print({
age:13,
firstName:"s",
secondName:"b",
})
将会报错,必须改为
print({
firstName:"s",
secondName:"b",
})
毫无疑问这也是个愚蠢的设计
用法例子:
网络请求,的参数用interface定义好
interface Param{
type:string;
url:string;
data ?:string; ?: 是可不传的意思
dataType:string;
}
function ajax(config: Param) {
var xhr = new XMLHttpRequest();
xhr.open(config.type, config.url, true);
xhr.send(config.data);
xhr.onreadystatechange=function(){
if(xhr.readyState == 4 && xhr.status == 200) {
if(config.dataType ==='json'){
JSON.Parse(xhr.responseText)
}else{
console.log(xhr.responseText)
}
}
}
}
接口被类实现
interface Animal{
eat():void;
}
interface Person extends Animal {
work():void;
}
class Web implements Person{
public name:string
constructor(name:string){
this.name = name
}
eat(){
console.log("eat")
}
work(){
console.log("work")
}
}
var ww = new Web("小吴")
class Programmer {
public coding(){
console.log("coding")
}
}
既继承,也实现接口
class GameDesigner extends Programmer implements Person {
public name:string
constructor(name:string){
this.name = name
}
eat(){
console.log("eat")
}
work(){
console.log("work")
}
}
类 类型接口
interface Animal{
name:string;
eat(str:string):void;
}
class dog implements Animal{
name:string;
constructor(name:string){
this.name = name;
}
辣鸡啊,不把参数放进去居然也是对的
eat(){
console.log("eat" + str)
}
}
接口继承接口
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Programmer implements Person{
public name:string
constructor(name:string){
this.name = name
}
eat(){
console.log(this.name + " eating")
}
work(){
console.log(this.name + " working")
}
}
用interface对函数的类型进行约束
interface encrypt{
(key:string, value:string)
}
var md5:encrypt = function(key:string, value:string):string{
}
function encryptPassword(encryptFunc:encrypt, password:string){
return encryptFunc(password, password)
}
使用interface约束数组
interface UserArr{
[index:number]:any
}
var arr:UserArr = ['aaa', 123, 'bbb'];
interface UserArr{
[index:string]:string
}
var arr:UserArr = {'a':'b', 'c':'d'}
泛型
interface ConfigFn{
<T>(value:T):T;
}
function getData<T>(value:T):T{
return value;
}
var mygetData:ConfigFn= getData;
mygetData<string>('kill')
指定T类型
interface ConfigFn{
<T>(value:T):T;
}
function getData<T>(value:T):T{
return value;
}
var mygetData:ConfigFn<string>= getData;
mygetData('kill')
泛型类
class MySQL<T>{
add(info:T):boolean{
console.log(info)
return true;
}
}
var db = new MySQL()
db.add(3); 可以随便传入
var db = new MySQL<string>()
db.add('abc'); 只能传入字符串
泛型接口只能由泛型类继承
interface DB<T>{
add(info:T):void;
}
class MySQL<T> implements DB<T>{
}
模块
export function getData():any{
return ""
}
export var externValue:number = 3
命名空间
namespace A{
interface Animal{
}
export class Dog { export之后才可以被命名空间外访问
}
class Cat{
}
}
var d = new A.Dog() 注意是 A.Dog
装饰器
function logclass(target:any){
console.log(target)
target.prototype.apiUrl = 'xxx'
}
@logclass
class HttpClient{
getData(){
}
}
装饰器就是那个 @logclass
会自动把class作为参数传进去
装饰器工厂
function logclass(param:string){
if (param === 'class'){
return function(target:any){
console.log(target)
}
}
}
@logclass('class')
class HttpClient{
getData(){
}
}
装饰器重载类方法
function logclass(target:any){
return class extends target{
getData(){
console.log("fuck world!")
}
}
}
@logclass
class HttpClient{
getData(){
console.log('hello world')
}
}
这样,装饰器就将类的方法给重载了
属性装饰器
function logproperty(param:string){
return function(target:any, attr:any){
console.log(target)
console.log(attr)
target[attr] = param;
}
}
@logclass
class HttpClient{
@logproperty('http')
public url:any |undefined;
getData(){
console.log('hello world')
}
}