Typed JavaScript at Any Scale.
添加了类型系统的 JavaScript,适用于任何规模的项目。
以上描述是官网对于 TypeScript 的定义。
它强调了 TypeScript 的两个最重要的特性——类型系统、适用于任何规模。
什么是TypeScript?
TypeScript就是所谓的JavaScript超集。它不是JavaScript的替代品,也不会为JavaScript代码添加任何新功能。相反,TypeScript允许程序员在其代码中使用面向对象的构造,然后将其转换为JavaScript。
ts中的继承
class Person{
name!:string;
age:number;
constructor(name:string, age:number) {
this.name = name;
this.age = age;
}
running(){
console.log(this.name + " running")
}
eating(){
console.log(this.name + " eating")
}
}
class A{}
//Classes can only extend a single class.
// class Student extends Person, A{
class Student extends Person{
learn: string;
constructor(name:string, age:number, learn: string) {
super(name, age);
this.learn = learn
}
running(){
//this ==> s
//super===> Person
super.running()
console.log(this.name + " Student running")
}
}
let s: Student = new Student("学生", 20, "TypeScript");
s.running();
s.eating();
console.log(s)
ts中的成员修饰符
//在typeScript中 类的属性和方法支持三种修饰符
//1 public
// 修饰的是在任何地方可见 公有的属性或方法 默认编写的属性就是public的
//2 private
// 修饰的是仅在同一类中可见 私有的属性或方法(不参与继承)
//3 protected
// 修饰的是仅在类自身及子类中可见 受保护的属性或方法(不能读写)
//4 readonly
// 修饰的是这个属性我们不希望外界可以任意的修改,只希望确定值之后直接使用(只能读)
class Person{
public name!:string;
public age:number;
constructor(name:string, age:number) {
this.name = name;
this.age = age;
}
running(){
console.log(this.name + " running")
}
eating(){
console.log(this.name + " eating")
}
}
class Student extends Person{
public learn: string;
constructor(name:string, age:number, learn: string) {
super(name, age);
this.learn = learn
}
running(){
//this ==> s
//super===> Person
super.running()
console.log(this.name + " Student running")
}
}
let s: Student = new Student("学生", 20, "TypeScript");
s.running();
s.eating();
console.log(s)
//private 修饰
class Person{
private name:string;
constructor(name:string) {
this.name = name;
}
}
let p = new Person("aa");
console.log("=======>",p)
//protected 修饰
class Person{
protected name:string;
constructor(name:string) {
this.name = name;
}
}
let p = new Person("aa");
//readonly 修饰
class Person{
readonly name:string;
constructor(name:string) {
this.name = name;
}
}
let p = new Person("aa");
ts中的抽象类
//多态 => 编译多态 运行多态
//编译多态=>指为不同数据类型的实体提供统一的接口(把相关的数据整合起来通过同一个接口去调用)
//运行多态=>重载和重写
//继承是多态(编译多态)使用的前提
//在定义很多通用的接口时,通常会让调用者传入父类, 通过多态来实现更加灵活的调用方式
//但是,父类本身其实并不需要对某些方法进行具体的实现,所以父类中定义的方法,可以定义为抽象方法
//抽象方法=>
//在ts中没有具体实现的方法(抽象方法)
//抽象方法, 必须存在于抽象类中
//抽象类必须使用 abstract声明
//抽象类=>
//抽象类是不能被实例化的(也就是不能通过new关键字来创建);
//抽象方法必须被子类实现, 否则该类必须是一个抽象类
//抽象类 abstract
abstract class Shape{//形状类
//抽象方法
abstract getArea():number
}
class Rectangle extends Shape{//矩形类
public width: number
public height: number
constructor(width: number, height: number) {
super()
this.width = width
this.height = height
}
getArea(){
return this.width * this.height
}
}
let rectangle = new Rectangle(100,100);
class Circle extends Shape{//圆形类
public r: number
constructor(r: number) {
super()
this.r = r
}
getArea(){
return this.r * this.r * 3.14
}
}
let circle = new Circle(100);
function getArea(shape:Shape){//获取面积
console.log(shape.getArea())
}
getArea(rectangle)// width height
getArea(circle)// R
//抽象类 不能使用new创建 不能被实例化
// let shape = new Shape()
// getArea(shape)//shape => {getArea(){}}
ts中的接口:interface
定义接口允许您检查变量组合以确保它们使用一致。接口不会转换为JavaScript; 他们唯一的目的是帮助开发者。例如,您可以使用以下属性和类型定义接口:
interface Food {
name: string;
calories: number;
}
interface的继承
interface Obj {
name: string,
run: () => void
}
interface Obj2 {
age: number
}
//接口是支持多继承的(类的继承只能继承一个)
interface Obj12 extends Obj, Obj2 {
jump: () => void
}
let obj: Obj12 = {
name: "你好",
age: 18,
run(){},
jump(){}
}
interface和type的区别
//我们发现interface和type都可以用来定义类型, 那么在开发过程中,到底应该选择哪个
//1. 如果定义的是对象类型,那么通常推荐使用interface
//2. 如果定义的是非对象 function Direction 推荐使用type
//interface和type之间有什么异同
//1.interface可以重复声明 type不能重复声明
//2.type定义的别名, 别名是不能重复
/*type Person = {
name: string,
run:()=>void
}
type Person = {
age: number
}*/
interface Person {
name: string,
run:()=>void
}
interface Person {
age: number
}
let obj: Person = {
name: "aa",
run(){},
age: 18
}
/*let img = document.getElementById("img") as HTMLImageElement
let div = document.getElementById("div") as HTMLDivElement
window.navigator.userAgent //==>当前浏览器信息
interface Window{
helloWorld: string
}
window.helloWorld = "你好世界"*/
ts中的泛型
//在开发过程中 一些时候我们声明的函数不仅仅要明确他的数据类型,而且还要考虑这个方法具有很强的可复用性
//实现类型参数化 ==>泛型
//定义一个方法,在方法中不去确定参数到底是什么类型,而是需要使用者来进行传递
interface IObj{
name: string,
age: number
}
//不确定用户传递什么类型的参数回来 那么也就不能确定返回值
//类型的参数化
//在定义这个函数的时候, 我们不去决定这些参数的类型
//而是让调用者以参数的形式告诉我们函数的参数应该是什么类型
//泛型函数
//函数中在函数名的后面通过<形参>的形式,接受传递过来的类型
function fn<T=string>(arg:T):T{
console.log(arg)
return arg
}
//泛型函数调用
//1通过<类型> 的方式将类型传递给函数
fn<string>("1234")
//2通过类型推导,自动的推导出我们传入变量的类型
// 在这里会推导出他们是字面量类型, 当然字面量类型对我们的函数也是适用的
fn<number>(123)
//引用类型会推导出想要的效果
fn<number[]>([1,2,3])
fn({a:1})
fn([1,2,3])
//通过泛型的形式来确定变量的数据类型
let arr: string[] = ["1","2","3"]
let arr1: Array<string> = ["1","2","3"]
let arr2: Array<number> = [1,2,3,4]
//泛型=> 泛指所有类型