Typescript在JS的基础上进行开发,是JavaScript的超集,能够支持JS的语法。同时,TypeScript也是一种强类型的语言,在编译时就会检查类型合法性(运行时也会检查),正如官网所说:“Typescript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.”
TS可编译成JS文件,其强大优势在于:强大类型系统,在编译期就能发现问题,增加代码的可维护性;增加了一些特殊的类型:元祖、泛型等,返回值也能定义数据类型;还有其他后续补充。
变量
变量使用let进行定义,如:let a : number = 10 。注意点如下:变量遵循局部变量和全局变量的区别,这与Java一致;同时,同一变量不可重新定义;若使用const定义,则表示变量的引用值不可变,不可重新赋值;但是被引用主体可变。例子如下:
const age = 10;
const temp2 = {
name: "alialiali",
age: age,
}
//报错
temp2 = {
name: "amiamiami",
age: age,
}
temp2.age=30;
//返回30
console.log(temp2.age);
因此,对于不可变的变量类型,通常使用“const”声明为常数;可变使用“let”进行声明。
常用的变量类型如下:
boolean | 布尔 |
number | 数字 |
string | 字符串 |
Array<number>或nubmber[ ] | 数组 |
tuple | 元组 |
enum | 枚举 |
any | 任意值 |
类型别名
可以使用type关键字定义类型,如下所示。
type mytype=1|2|3|4|5|6;
let a:mytype;
解构
结构包含数组解构和对象结构。意思是获取到数组或是对象中的值。
数组解构
意思是批量获取数组中的元素值。定义数组后,用 “[ ]” 包裹元素名称。如下所示:
let input=[1,2,3];
let [firstvar,secondnum]=input;
console.log(firstvar);//输出1
解构部分的内容还需要深入理解。
接口
接口用来定义/限定类的结构,接口内部可以包含属性和方法,但只能定义属性和方法,不能赋值。接口可以重复声明,最后的结果是合并后的结果。例子如下:
(1)
interface myIner {
name: string;
age: number;
sayHello(var1: number, var2: number): number;
}
class MyClass implements myIner {
name: string;
age: number;
var1: number;
var2: number;
constructor(name: string, age: number, var1: number, var2: number) {
this.age = age;
this.name = name;
this.var1 = var1;
this.var2 = var2
}
sayHello(var1: number, var2: number) {
return (var1 + var2);
}
}
const myclass = new MyClass("jack",10,2,3);
// let res = myclass.name
console.log(myclass.sayHello(10,10));
interface LabelledValue {
label: string;
}
function printLabel(labbelled:LabelledValue):{color:string;area:number}{//这里右边的{}表示类型检查
console.log(labbelled.label);
}
let obj = {label:"this is 500 labels",name:"pidx"};
printLabel(obj);
(3)接口中的参数可选,加上问号 “?” 即可。
//可选参数练习
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig) {
let newSquare = { color: "white", area: 10 };
if (config.color) {
newSquare.color = config.color;
}
if (config.width) {
newSquare.area = config.width * config.width;
}
return newSquare;
}
let mySquare = createSquare({ color: "black" });
console.log(mySquare.area);//返回10
console.log(mySquare.color);//返回black
接口中的参数还可设置为“readonly”属性,仅可读。
接口中的函数定义
接口中也能定义函数,一般来说,函数需要参数和返回值,其在接口中的定义为:“(参数1:参数1类型 , 参数1:参数1类型) : 返回值类型”。
//接口的函数定义练习
interface Calc {
//定义两个参数类型以及返回值类型
(var1: number, var2: number): number;
}
let add: Calc = (n1: number, n2: number) => {
return (n1 + n2);
}
//另一种形式
let mult: Calc;
mult = function (n1: number, n2: number) {
return (n1 * n2);
}
console.log(add(10, 10));
console.log(mult(10, 10));
接口的继承
《需补充demo》
类
类的使用是面向对象的,与其他面向对象语言中的类的使用方法类似。比如,包含成员变量、方法、函数等,能够被继承、实例化,也有抽象化的类等。
类中的属性
类中的属性包括静态属性、实例属性等,属性的访问权限有public、protected、private(默认是public)。
属性修饰符
public:公有。
protected:只能在本类及其派生类中使用,派生类包含子类。
private:只能在本类中使用,不能在派生类中使用。
enum Gender {
male = 0,
female = 1
}
class Person {
name: string = "孙悟空";
age: number = 30;
static gender: Gender=Gender.female;
private hobby: string = "翻跟头"
}
let jack = new Person();
console.log(jack)//输出Person { name: '孙悟空', age: 30, hobby: '翻跟头' }
console.log(Person.gender)//输出1
// console.log(jack.hobby)//无法通过编译。
上述例子并未充分利用类的面向对象属性,需要借助constructor方法。首先在类中定义成员变量,但不赋值;然后借助constructor方法给成员变量赋值,最后构建对象时,传入参数并运行其中的方法。如下所示:
class Person {
name: string;
gender: Gender;
constructor(name: string, gender: Gender) {
this.name = name;
this.gender = gender
}
inform() {
console.log("his name is " + this.name + ",and gender is " + this.gender);
}
}
let jack = new Person("Jack", Gender.female);
jack.inform()//his name is Jack,and gender is 1
let smith = new Person("Smith", Gender.male);
smith.inform()//his name is Smith,and gender is 0
属性的存取器
typescript中,将属性私有化之后,也可以使用类似的getter/setter方法。如下所示:
//属性存取器
class Person {
private name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
getName() {
return this.name;
}
setName(value: string) {
this.name = value;
}
}
const smith = new Person('smith', 30);
smith.setName("alpha");
console.log(smith);//Person { name: 'alpha', age: 30 }
上述例子中,getName方法也可替换为:
get name{
return this.name;
}
类的继承
类的继承与其他面向对象的方法一致,也支持方法的重写。属性的传播遵循public、private、protect等。方法方面,如果子类想要使用父类的方法,使用super即可。此外,子类会默认调用父类的constructor,若子类重写constructor,则必须要在constructor中调用super()方法。如下所示。
class Person {
name: string;
gender: Gender;
constructor(name: string, gender: Gender) {
this.name = name;
this.gender = gender
}
inform() {
console.log("his name is " + this.name + ",and gender is " + this.gender);
}
}
class Chinese extends Person {
anthem: string;
constructor(name: string, gender: Gender, anthem: string) {
super(name, gender);
this.anthem = anthem;
}
sing() {
console.log("升旗要唱" + this.anthem);
}
}
let wang = new Chinese("王大锤", Gender.male, "国歌");
wang.inform();//his name is 王大锤,and gender is 0
wang.sing();//升旗要唱国歌
抽象类
使用abstract修饰类后,该类不可被实例化,但可以被继承。抽象类中可以包含抽象方法,当抽象类被继承时,抽象方法必须被重写,否则会报错。
函数
函数需要参数、返回值,包括显式函数和匿名函数。
两者形式如下:
//显性函数
function add(x:number , y:number):number{
return x + y;
}
//匿名函数
let myAdd = function(x:number , y:number):number{
return x + y;
}
泛型
在定义函数或是类时,如果类型不明确,则可以使用泛型。
以函数为例,一般情况下的函数函数定义如下:
function pre_fun(a:number):number{
return a;
}
即参数类型和返回值类型均确定。但是,当参数类型和返回值均不确定时,需要使用泛型:
// 泛型练习
function fun<T>(a: T): T {
return a;
}
let myfun1 = fun(12);//自动推断类型,此时T为number
let myfun2 = fun<string>("helloword!")//手动设置类型,T=string
console.log(myfun1);
console.log(myfun2);