function getTotal1(one: number, two: number): number {
return one + two;
}
const total1 = getTotal1(1, 2);
3-1、void无返回值类型:
有时候函数是没有返回值的,比如现在定义一个sayHello
的函数,这个函数只是简单的terminal
打印,并没有返回值,就可以给他一个类型注解void
,代表没有任何返回值
function sayHello(): void {
console.log("hello world");
}
3-2、never类型:
如果一个函数是永远也执行不完的,就可以定义返回值为never
,那什么样的函数是永远也执行不完的那?我们先来写一个这样的函数(比如执行执行的时候,抛出了异常,这时候就无法执行完了)。
function errorFuntion(): never {
throw new Error();
console.log("Hello World");
}
还有一种是一直循环,也是我们常说的死循环,这样也运行不完,比如下面的代码:
function forNever(): never {
while (true) {}
console.log("Hello JSPang");
}
4.数组类型的定义
简单数组类型:
const numberArr = [1, 2, 3];
const stringArr: string[] = ["a", "b", "c"];
const numberArr: number[] = [1, 2, 3];
const undefinedArr: undefined[] = [undefined, undefined];
数组中如果有多类型:
const arr: (number | string)[] = [1, "string", 2];
数组中的对象类型定义:
const yihuanhuan5: {name: string, age: Number }[] = [ { name: "刘英", age: 18 }, { name: "谢大脚", age: 28 }, ]
这种形式看起来比较麻烦,而且如果有同样类型的数组,写代码也比较麻烦,TypeScript 为我们准备了一个概念,叫做类型别名
定义别名的时候要以type
关键字开始,现在定义一个Lady
的别名
type Lady = { name: string, age: Number };
const yihuanhuan5: Lady[] = [ { name: "刘英", age: 18 }, { name: "谢大脚", age: 28 }, ];
5.元组的使用和类型约束
元组:把数组中的每个元素类型的位置给固定住了,这就叫做元组
const xiaojiejie: [string, string, number] = ["dajiao", "teacher", 28];
const xiaojiejies: [string, string, number][] = [ ["dajiao", "teacher", 28], ["liuying", "teacher", 18], ["cuihua", "teacher", 25], ];等价于
const xiaojiejies: {string, string, number}[] = [ ["dajiao", "teacher", 28], ["liuying", "teacher", 18], ["cuihua", "teacher", 25], ];
目前元组用的较少,因为其完全可以用对象类型代替
6.interface接口
TypeScript的核心原则之一是对值所具有的结构进行类型检查,在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约
我们可以把重复的类型注解,定义成统一的接口
interface Girl {
name: string;
age: number;
bust: number;
}
const fun1 = (yihuanhuan6:Girl) => {
console.log(yihuanhuan6.name, 'yihuanhuan6.name')
console.log(yihuanhuan6.age, 'yihuanhuan6.age')
console.log(yihuanhuan6.bust, 'yihuanhuan6.bust')
}
const girls = {
name: 'test1',
age: 18,
bust: 23
}
fun1(girls)
接口和类型别名的区别:
6-1、写法区别
类型别名实例:
type Lady = { name: string, age: Number };
const yihuanhuan5: Lady[] = [ { name: "刘英", age: 18 }, { name: "谢大脚", age: 28 }, ];
接口实例:
interface Lady {
name: string;
age: Number
};
const yihuanhuan5: Lady[] = [ { name: "刘英", age: 18 }, { name: "谢大脚", age: 28 }, ];
6-2、类型别名可以直接给类型,而接口必须代表对象
type Girl1 = stirng;
6-3、接口的非必选项得定义(接口的一些特性,类别别名没有)
定义的方式是在冒号“:”前面加“?”
interface Girl {
name: string;
age?: number;
bust: number;
}
const fun1 = (yihuanhuan6:Girl) => {
console.log(yihuanhuan6.name, 'yihuanhuan6.name')
if(yihuanhuan6.age){
console.log(yihuanhuan6.age, 'yihuanhuan6.age')
}
console.log(yihuanhuan6.bust, 'yihuanhuan6.bust')
}
6-4、接口允许加入任意值
interface Girl {
name: string;
age?: number;
bust: number;
[propname: string]: any;
}
这个的意思是,属性的名字是字符串类型,属性的值可以是任何类型
实例如下:
const fun1 = (yihuanhuan6:Girl) => {
console.log(yihuanhuan6.name, 'yihuanhuan6.name')
if(yihuanhuan6.age){
console.log(yihuanhuan6.age, 'yihuanhuan6.age')
}
console.log(yihuanhuan6.bust, 'yihuanhuan6.bust')
yihuanhuan6.sex && console.log("性别是:"+yihuanhuan6.sex)
}
const girls = {
name: 'test1',
// age: 18,
bust: 23,
sex:'女'
}
fun1(girls)
6-5、接口里的方法
接口里不仅可以存属性,还可以存方法
interface Girl {
name: string;
age?: number;
bust: number;
[propname: string]: any;
say(): string;
}
6-6、接口和类的约束
interface Girl {
name: string;
age?: number;
bust: number;
[propname: string]: any;
say(): string;
}
class Yihuanhuan implements Girl {
name = "易欢欢";
age = 12;
bust = 34;
sex = '女';
say(){
return '12313'
}
}
6-7、接口之间的继承
接口也可以用于继承的,比如你新写一个Teacher
接口,继承于Girl 接口,一个接口可以继承多个接口,创建出多个接口的合成接口。
interface Girl {
name: string;
age?: number;
bust: number;
[propname: string]: any;
say(): string;
}
interface Yi extends Girl {
teach(): string;
}
class Yihuanhuan1 implements Yi {
name = "易欢欢";
age = 12;
bust = 34;
sex = '女';
say(){
return '12313'
};
teach(): string {
return '我在教书'
}
}
子接口继承父接口,那么子接口就拥有了父接口的访问父接口所有公用属性和方法的能力,同时还可以自己新定义一些属性和方法
6-8、接口继承类
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的private和protected成员。
这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。
举个栗子:
class Control {
private state: any;
}
interface SelectableControl extends Control {
select(): void;
}
class Button extends Control implements SelectableControl {
select() { }
}
class TextBox extends Control {
select() { }
}
// 错误:“Image”类型缺少“state”属性。
class Image implements SelectableControl {
select() { }
}
7.类的概念和使用
7-1、类的基本使用:
class Lady {
content = "Hi,赛高";
sayHello() {
return this.content;
}
}
const goddess = new Lady();
console.log(goddess.sayHello());
7-2、类的继承
TypeScrip 的继承和ES6
中的继承是一样的,关键字也是extends,子类继承父类,那么子类就拥有了访问父类所有公用属性和方法的能力
class Lady {
content = "Hi,lisa";
sayHello() {
return this.content;
}
}
class lisa1 extends Lady {
sayLove() {
return "I love you";
}
}
const goddess = new lisa1();
console.log(goddess.sayHello());
console.log(goddess.sayLove());
7-3、类的重写
重写就是子类可以重新编写父类里边的代码
class XiaoJieJie extends Lady {
sayLove() {
return "I love you!";
}
sayHello() {
return "Hi , honey!";
}
}
7-4、super关键字使用
当我们在继承父类的时候,在子类里面还想用到父类中的一些方法,就需要用到super关键字了
class Lady1 {
text = "我是父亲的内容";
sayHello(){
return '我是父亲的方法'
}
}
class Luipte extends Lady1 {
name = '李四';
sayHello(){
return '我是'+this.name+',后面的内容来自我爸爸'+super.sayHello()+this.text
}
}
const son1 = new Luipte()
console.log(son1.sayHello())
7-5、typescript中类的访问类型
类的访问类型就是基于三个关键词private
、protected
和public
,也是三种访问类型,TypeScript里,成员都默认为 public
public类型:public
从英文字面的解释就是公共的
或者说是公众的
,在程序里的意思就是允许在类的内部和外部被调用
private类型:只允许在类的内部被调用,外部不允许调用
protected类型:允许在类内及继承的子类中使用
class Person1 {
public name:string = "";
private ago:number = 0;
protected text:string = "1212";
readonly color:string ="red";
public sayHello(){
// 类内
console.log(this.name +this.ago+this.text+ 'say Hello')
}
}
//-------以下属于类的外部--------
const person = new Person1()
person.name = 'yihuanhuan.com' // 不会报错
// person.age = 12 // 会报错
// person.text = "rrrrrr" // 会报错
// person.color = "yellow" // 会报错
console.log(person.color) // 可以读取
person.sayHello()
class Son extends Person1 {
public sayBy(){
console.log(this.text + '121122') // 不会报错
}
}
7-6、类的构造函数
比如,我们在使用类,new一个实例对象的时候,想要直接通过传递参数的形式,给里面的属性赋值,此时就需要用到构造函数,关键字是constructor
class Person2{
public name :string;
constructor(name:string){
this.name=name
}
}
const person2= new Person2('易欢欢')
console.log(person2.name)
还可以简写成:
class Person3{
constructor(public name:string){
//这种写法就相当于你定义了一个name
,然后在构造函数里进行了赋值,这是一种简化的语法,在工作中我们使用这种语法的时候会更多一些
}
}
const person3= new Person3('周工')
7-7、继承类的构造器
在子类中使用构造函数需要用super()
调用父类的构造函数
class Person4 extends Person2 {
constructor(public age:number){
super('周工')
};
sayHello(){
console.log(this.name +'今年是'+this.age +'岁啦!')
}
}
const person4 = new Person4(26)
person4.sayHello()
子类继承父类并有构造函数的原则,就是在子类里写构造函数时,在构造函数里访问 this
的属性之前,我们 一定要调用 super()
,如果需要传值,也必须进行传值操作。就是是父类没有构造函数,子类也要使用super()
进行调用,否则就会报错。
这个是TypeScript强制执行的一条重要规则。
7-8、类的 Getter 和 Setter 和static(通过 Getter 和 Setter 的形式来访问和修改这个属性。)
class Person5 {
constructor(private _age:number){}
get age(){
return this._age-10
}
set age(age:number){
this._age=age+3
}
}
const person5 = new Person5(28)
person5.age=25
console.log(person5.age)
学习类,都知道要想使用这个类的实例,就要先New
出来(),但是有时候不想要new实例,想要直接使用类里面的方法
此时用static
声明的属性和方法,不需要进行声明对象,就可以直接使用
class Person6 {
static sayLove() {
return "yihuanhuan";
}
}
console.log(Person6.sayLove());
7-9、抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract
关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class Animal {
abstract makeSound(): void; // 抽类型中的抽象方法不包含具体实现,在派生类中必须实现
move(): void { // 抽象类中的普通方法可以包含具体实现
console.log('roaming the earch...');
}
}
抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含 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(); // 错误: 方法在声明的抽象类中不存在