如果代码中有export import 之类的代码,那这个文件会变成一个模块
export {};
let name:strting = 'yzl';
基础类型定义
字符串数组
let hobbies:string[] = ['1','2','3'];
let str:Array<string> = ['4','5','6'];
元组
元组 类似一个数组它是一个长度和类型都固定的数组
let point:[number,number] = [100,100];
let person:[string,number] = ["yzl",100];
类数组
function sum(...arg:any):void {
let args: IArguments = arguments;
return Array.from(args).reduce((res,item)=>res+item)
}
console.log(sum(1,2,3,4,5));
枚举类型(enum)
枚举的值不可以是表达式比如
enum Week {
MONDAY = new Date()
}
普通枚举
枚举就是自己关联自己
enum Gender {
boy,
girl
}
console.log(Gender.boy);
转换了之后
var Gender;
(function (Gender) {
Gender[Gender["boy"] = 0] = "boy";
Gender[Gender["girl"] = 1] = "girl";
})(Gender || (Gender = {}));
console.log(Gender.boy);
常数枚举
const enum Gender {
boy,
girl
}
console.log(Gender.boy);
转换了之后 直接变成常数
console.log(0 /* boy */);
null 和 undefined 是其他类型的子类
nerver 永远不可能出现的值(就是报错或者死递归)
function createError(message:string):never {
console.log(1);
throw new Error("error");
console.log(2);
}
猜类型和推论类型
let num:string | number;
num = 'hellow';
num = 2;
断言
let num:string | number;
num = 'hellow';
num = 2;
//把num断言成number类型
console.log((num as number).toFixed(2));
字面量类型
let Gender:'Boy' | 'GIRL';
Gender = 'Boy';
Gender = 'GIRL';
函数定义
// type 用来定义一个类型或者类型别名字
type G = (name:string)=>void
// 函数定义
let t:G = function (name:string):void {
console.log(`你好`+ name);
}
t('yzl');
可选参数
function print(name:string,age?:number,home?:string){
}
print('yzl');
print('yzl',21);
print('yzl',21,'温州');
print();
剩余参数
function sum(...res:Array<number>){
res.reduce((accu,item)=>accu + item,0);
}
重载
function sum(x:number,y:number):void;
function sum(x:string,y:string):void;
function sum(x:any,y:any){
console.log(x,y)
}
sum(10,20);
sum('10','20');
类中的get方法
class Person {
age:number;
constructor (){
this.age = 10;
}
//这个东西算是属性
get getAge(){
return this.age;
}
//这个东西算是属性
set setName(val:string){
this.name = val;
console.log(1)
}
}
console.log(new Person)
使用public公开形参变为实例属性
namespace b {
class Person {
constructor(public name:string){
}
}
let p1 = new Person("尤子龙");
console.log(p1.name)
}
继承
//父类
class Person {
name:string;
getName():void{
console.log(this.name);
}
constructor(name:string){
this.name = name;
}
}
//子类
class Son extends Person {
constructor(){
super('尤子龙');
}
}
/* let p = new Person();
p.getName(); */
let S = new Son();
S.getName();
装饰器
类装饰器
修饰类 target 指向 类本身Person
// 类装饰器
namespace a {
//这个会和 Person 合并
interface Person {
name:string
}
function decorator(target:any):void{
target.name = 'yzl'
}
@decorator
class Person {
constructor(){
}
}
console.log(new Person().name)
}
属性修饰器
普通属性
如果给属性添加修饰器他会有两个参数
- target 指向类的原型 既
Person.prototype
- name 是属性的名字
namespace a {
function decorator(target:any,name:string){
target.name = '12312'
}
class Person {
@decorator
name:string = 'zhufeng';
constructor(){
}
}
console.log(new Person().name)
}
静态属性
如果给属性添加修饰器他会有两个参数
- target 指向类的原型 既
Person
- name 是属性的名字
namespace a {
function decorator(target:any,name:string){
target.name = '12312'
}
class Person {
@decorator
static name1:string = 'zhufeng';
constructor(){
}
}
console.log(Person.name1)
}
方法修饰器
方法修饰器接受三个参数
- target 指向原型对象
- name 方法名字
- propertyDecorator 属性描述
- value 是一个函数
namespace a {
function decorator(target: any, name: string, propertyDecorator: PropertyDescriptor) {
// 这里是旧方法
let oldMethod = target[name];
//重写value
propertyDecorator.value = function (...args:any[]) {
let res = args.map(v=> parseFloat(v));
return oldMethod(...res);
}
}
class Person {
static name1: string = 'zhufeng';
@decorator
sum(...arg: any[]): any {
return arg.reduce((res, item) => res + item);
}
}
console.log(new Person().sum("1", 2, 3, 4))
}
参数修饰器
参数修饰器接受三个参数
- target 指向原型对象
- name 函数名称
- paramsIndex 参数下标
namespace a {
function addage(target: any, name: string, index: Number) {
console.log(target,name,index);
}
class Person {
getData(@addage kkk: any):void {
}
}
console.log(new Person().getData(123))
}
修饰器的执行顺序
分析
//方法装饰器
function logmethod(params:any){
return function(target:any,methodName:any,desc:any){
console.log(target); // HTTP
console.log(methodName); //getData
console.log(desc);
// 1保存当前方法
var oldMethod = desc.value;
desc.value = function(...args:any[]){//用三点运算符来接收传入的数组参数
args = args.map((value)=>{
return String(value);
})
console.log(args);
oldMethod.apply(this,args);
}
}
}
class HttpClient{
public apiUrl:string | undefined;
constructor(){
}
@logmethod('www.baidu.com')
getData(...args:any[]){
console.log(args);
console.log("我是getData里面的方法");
}
}
var http = new HttpClient();
http.getData("123","xxx");
总结:
属性方法先执行,谁先写谁先执行
方法执行的时候,先参数再方法,而且他们一定会在一起
最后是类
如果是同类型,先执行后写
接口
记住一句话 接口只声明不定义
抽象类 abstract
抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含
abstract
关键字并且可以包含访问修饰符。
抽象类可以只声明 但是不定义
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log('Department name: ' + this.name);
}
abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountingDepartment extends Department {
constructor() {
super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
}
printMeeting(): void {
console.log('The Accounting Department meets each Monday at 10am.');
}
generateReports(): void {
console.log('Generating accounting reports...');
}
}
let department: Department; // 允许创建一个对抽象类型的引用
// department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
// department.generateReports(); // 错误: 方法在声明的抽象类中不存在
可以用来描述对象,对象有什么类型
interface point {
name:string,
age:Number
}
let obj:point = {name:'yzl',age:18};
可以用来描述行为(方法)抽象
interface a {
speak():void
}
interface b {
eat():void
}
class person implements a,b {
speak(){
console.log("a.speak")
}
eat(){
console.log("b.eat")
}
}
new person().eat()
重写方法
// 动物类
class zoon {
speak():void{
console.log("嗷嗷叫");
}
}
class cat extends zoon {
speak():void{
console.log("喵喵喵");
}
}
new cat().speak();
任意属性
// 任意属性
namespace a {
interface constraint {
[propName:string]:string | number
}
let obj:constraint = {
name:'尤子龙',
age:20
}
}
接口之间的继承
interface a{
A():void;
}
interface b {
B():void;
}
class person implements b,a {
A(){};
B(){}
}
//接口之间的继承
interface a{
A():void;
}
interface b extends a{
B():void;
}
class person implements b {
A(){};
B(){}
}
只读接口
// 只读接口
namespace a {
interface circleAble {
readonly PI: number;
Rs: number
}
let obj: circleAble = {
PI : 3.14,
Rs : 10
}
console.log(obj.PI)
console.log(obj.PI = 4) // 错误
}
接口约束函数
namespace a{
interface a {
(x:number,y:string):void;
}
let fn:a = function (x:number,y:string):void {
console.log(`${y}今年${x}岁了`);
}
fn(20,"尤子龙");
}
约束数组
// 约束 数组或者对象
interface a {
[index:number]:string
}
// let arr:a = ['1',2];//报错
// 数组
let arr:a = ['1','2'];
// 对象
let arr: a = {
0: '1',
1: '2'
};
泛型
就是说 定义函数的时候 T是什么类型我不知道 , 我在调用函数的时候再给他指定
namespace a {
function createArr<T>(age:T):void {
console.log(age);
}
createArr<number>(20);
}
函数接口泛型
// 接口泛型
interface a {
<T>(name:T,age:number):void;
}
let show:a = function <T>(name:T,age:number):void {
console.log(name,age);
}
show("尤子龙",21);
在函数中使用泛型的时候由于预先不知道具体的类型,所以不能访问到相应类型的方法
namespace a {
// 在函数中使用泛型的时候由于预先不知道具体的类型,所以不能访问到相应类型的方法
function name<T>(params:T) {
console.log(params.age);
}
name<object>({age:12})
}
type VS interface
interface 定义一个实实在在的接口,它才是一个真正的类型
type 一般用来定义别名并不是真正的类型
相同点
- 都可以描述一个对象或者函数
- 都允许拓展(extends)
不同点
- type 可以声明基本类型别名,联合类型,元组等类型
- type 语句中还可以使用 typeof 获取实例的 类型进行赋值
- interface 能够声明合并
interface
interface User {
name: string
age: number
}
interface SetUser {
(name: string, age: number): void;
}
type
type User = {
name: string
age: number
};
type SetUser = (name: string, age: number)=> void;
都允许拓展(extends)
interface 和 type 都可以拓展,并且两者并不是相互独立的,也就是说 interface 可以 extends type, type 也可以 extends interface 。 虽然效果差不多,但是两者语法不同。
interface extends interface
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
123456
type extends type
type Name = {
name: string;
}
type User = Name & { age: number };
1234
interface extends type
type Name = {
name: string;
}
interface User extends Name {
age: number;
}
123456
type extends interface
interface Name {
name: string;
}
type User = Name & {
age: number;
}
123456
不同点
type 可以而 interface 不行
type 可以声明基本类型别名,联合类型,元组等类型
// 基本类型别名
type Name = string
// 联合类型
interface Dog {
wong();
}
interface Cat {
miao();
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]
123456789101112131415
type 语句中还可以使用 typeof 获取实例的 类型进行赋值
// 当你想获取一个变量的类型时,使用 typeof
let div = document.createElement('div');
type B = typeof div
123
其他骚操作
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
1234567
interface 可以而 type 不行
interface 能够声明合并
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
12345678910111213141516
总结
一般来说,如果不清楚什么时候用interface/type,能用 interface 实现,就用 interface , 如果不能就用 type 。
super
- super一种是在构造函数中给父类的构造函数传参
- 一种是代表父类的原型对象
第一种情况
// 动物类
class zoon {
constructor(public name:string){
this.speak()
}
speak():void{
console.log(this.name + "嗷嗷叫");
}
}
class cat extends zoon {
constructor(name:string){
super(name);
}
}
new cat('尤子龙').speak();
第二种情况
// 动物类
class zoon {
constructor(public name:string){
this.speak()
}
speak():void{
console.log(this.name + "嗷嗷叫");
}
}
class cat extends zoon {
constructor(name:string){
super(name);
}
callSpeak(){
super.speak()
}
}
new cat('尤子龙').callSpeak();