安装ts : npm i -g typescript
编译ts文件: tsc test.ts
let a : number
let b : string = '123'
function func(c : boolean) : string {
return c ? '123' : '321'
}
描述变量的值为类型的本身
let d : 'A' | true | 2
d = 'A'
d = true
d = 2
let a : any
表示任意类型,一个变量设置类型为any后视为放弃TS类型检测,相当于JS
let a
如果声明变量不指定类型,TS解析器会将该变量视为any
let d : 'A' | true | 2
let e : any
d = e
当变量的类型为any时,赋值给任何类型的变量都不会报错
类型为unknown的变量,可以给自己赋值任何类型的值,但不能直接赋值给其他变量
let d : 'A' | true | 2
let e : unknown
if(e === 'A'){
d = e
}
let a : string
let b : unknown
if(typeof b === 'string'){
a = b
}
用来表示空,一般用在函数返回值,表示没有返回值
function func() : void{
return null
}
function func1() : void{
return undefined
}
没有返回值的函数,默认分配void类型
function warnUser() {
console.log("This is my warning message");
}
表示变量某种不可能存在的情况
const a = 123;
if (a !== 123) {
const b = a; // b: never
}
表示函数永远不会返回结果,但是可用来做抛出错误的函数
function func1() : never{
throw new Error('错误')
}
function fun2(): never {
return process.exit(1)
}
function fun3(): never {
while (true) {
}
}
某些时候never可以用来检查代码是否严谨或者是否遗漏
举例:
type All = string | number
function handle(val : All) {
switch (typeof val) {
case 'string':
break;
case 'number':
break;
default:
const a : never = val
break;
}
}
let a : object
a = { }
a = function () { }
let a:{name : string,age? : number,sex? : string}
a = {name : '111',sex : '男'}
let a : {name : string , [propName : string] : any}
a = {name : '111',age : 12, true : 1, 1 : '123'}
let d : (a : number, b : number) => number
d = function (n1 : number,n2 : number):number {
return 0
}
数组
let a : string[ ]
a = [ 'a' , 'b' , 'c']
let b : Array<number>
b = [1, 2, 3]
let c : (string | number | boolean)[ ];
c = [1 , 1, 'a', true]
长度、类型、顺序固定的数组
let a: [string, number, boolean]
a = ['1', 1, false]
列举一些类型
enum MyType {
A = 1,
B,
C
}
let a : MyType
a = MyType.A
enum MyType{
A = 100,
B = 99,
C
}
console.log(MyType.A === MyType.C);//true
let a : string
let b : unknown
a = b as string
a = <string>b
对于一些复杂的自定义类型,可以用type声明的变量来接收
type mytype = { name : string } & { age : number} & { gender : string}
let a : mytype = {
name : 'zza',
age : 26,
gender : '男'
}
interface myInterface {
name:string,
age:number
}
接口是为变量或者类制定一个规则或者标准,实现时需要去遵守。
变量声明接口类型时,属性要保持一致
const a : myInterface = {
name:'zza',
age:26
}
类实现接口时,属性实现可以多但不能少
class myClass implements myInterface{
name: string
age: number
gender: string
getInfo():string{
return this.name
}
}
interface myInterface {
name:string,
age:number,
gender?:string
}
interface myInterface {
name:string,
age:number,
readonly gender:string
}
const 用来修饰变量,readonly 用来修饰属性
一般用在对象变量上
interface myInterface {
name:string,
age:number,
[propName: string]: number | string;
}
const a : myInterface = {
name:'zza',
age:26,
addr:'123'
}
用在类中,意义不大
class myClass implements myInterface{
name: string
age: number
[propName: string]: number | string
constructor(name:string,age:number,propName:number | string){
this.name = name
this.age = age
this.propName = propName
}
}
const obj = new myClass('zza',26,12)//myClass {name: "zza", age: 30, propName: 12}
console.log(obj);
interface myInterface {
name:string,
age:number,
[propName: number]: number
}
const a : myInterface = {
name:'zza',
age:26,
123:0
}
extends
interface myInterface {
name:string,
age:number,
}
interface myInterface2 extends myInterface{
addr:string
}
class myClass {
phone:string
emil:string
}
interface myInterface3 extends myClass{
call():void;
}
type A = number;
type B = A | string | 'A'
interface A {
name: string
}
合并写法
type A = {
name:string,
age:number
}
type B = A & {
gender:string
}
interface A {
name:string,
age:number
}
interface B extends A {
gender:string
}
interface A {
name:string,
age:number
}
interface A {
gender:string
}
class A {
name : string
constructor(name:string){
this.name = name
}
getInfo(){
console.log(this.name);
}
}
class B extends A {
age:number
constructor(name:string, age:number){
super(name)
this.age = age
}
getInfo() {
super.getInfo()
console.log(this.age);
}
}
const a = new B('zza',26)
console.log(a);
a.getInfo()
class Person {
readonly name: string = 'abc'
constructor(name: string) {
this.name = name
}
}
let john = new Person('John')
属性和方法默认为公有,自己、类外和子类均可调用
属性和方法只能在自己类中调用
属性和方法可以在自己和子类中调用
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
protected getName():string{
return this.name
}
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
getWorkInfo() {
return `我叫${this.getName()},我工作在${this.department}`;
}
}
let aEmployee = new Employee('durban', '华盛顿');
console.log(aEmployee.getWorkInfo());
注意:readonly 与 上述修饰符不冲突,可以联合使用
class A{
private _name:string
constructor(name:string){
this._name = name
}
get name(){
return this._name
}
set name(value:string){
this._name = value
}
}
class Person {
name1: string = 'A'
static name2: string = 'B'
}
console.log(Person.name2)
console.log(new Person().name1)
class A {
private static age:string = '26'
private name:string = 'zza'
getInfo(){
return this
}
static getStaticInfo(){
return this
}
}
console.log(A.getStaticInfo());
console.log(new A().getInfo());
abstract class Animal {
abstract name:string
constructor() {
}
abstract say():void;
run():void{
console.log('跑');
}
}
abstract class sAnimal extends Animal{
abstract age:number
}
class Dog extends sAnimal {
name: string;
age: number;
run(): void {
super.run()
}
say(): void{
console.log('叫');
}
}
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
abstract eat(): any;
run() {
console.log('动物跑');
}
}
class Cat extends Animal {
eat() {
return "吃鱼";
}
}
class Dog extends Animal {
eat() {
return "吃肉";
}
// run() {
// console.log('狗跑');
// }
}
var cat: Animal = new Cat("猫");
var dog: Animal = new Dog("狗");
let fun: (x: Animal) => void = (x: Animal) => {
console.log(x.name + x.eat());
}
fun(cat)
fun(dog)
cat.run()
dog.run()
区别:
interface A {
name : string
}
class B implements A {
name: string //必须
age : string
}
abstract class A {
abstract name : string
}
class B extends A {
name: string //必须
age : number
}
interface A1 {
name : string
}
interface A2 {
age : number
}
interface A3 {
gender : string
}
class B implements A1,A2,A3 {
name: string //必须
age : number //必须
gender: string //必须
}
abstract class A {
abstract name : string
addr:string
}
class B extends A {
name: string //必须
addr:string //非必须
age : number
}
共同点:
js:
// 命名函数
function fun1(x, y) {
return x + y
}
// 匿名函数
let fun2 = function(x, y) {
return x + y;
}
ts中增加类型声明:
function fun1(x: number, y: number): number {
return x + y
}
let fun2 = function(x: number, y: number): number {
return x + y
}
对于给变量指定类型赋值的完整写法
let myAdd2: (x: number, y: number) => number =
function(x: number, y: number): number {
return x + y
}
function fun(a: string='A', b?: string): string {
if (b) {
return a + '-' + b
} else {
return a
}
}
console.log(fun('1', '2'))
console.log(fun('3'))
console.log(fun())
function letters(x: string, ...args: string[]) {
console.log(x, args)
}
letters('abc', 'c', 'b', 'a')
// 重载函数声明
function add (x: string): string
function add (x: number): number
// 定义函数实现
function add(x: string | number): string | number {
if (typeof x === 'string') {
return x
} else if (typeof x === 'number') {
return x
}
}
const a : number = add(1)
const b : string = add('1')
console.log(a)
console.log(b)
function fun<T,K>(a:T,b:K):T{
console.log(b);
return a
}
fun<string,number>('123',123)
实际使用:
function getNumberArr(value:number,count:number):number[] {
const a : number[] = []
for(let i = 0;i < count;i++){
a.push(value)
}
return a
}
function getStringArr(value:string,count:number):string[] {
const a : string[] = []
for(let i = 0;i < count;i++){
a.push(value)
}
return a
}
const arr = getNumberArr(123,10)
console.log(arr[0].toFixed());
const arr2 = getStringArr('123',10)
console.log(arr2[0].length);
利用泛型:
function getArr<T>(value:T,count:number):T[] {
const a : T[] = []
for(let i = 0;i < count;i++){
a.push(value)
}
return a
}
const arr3 = getArr<string>('123',10)
const arr4 = getArr<number>(123,10)
console.log(arr3[0].length);
console.log(arr4[0].toFixed());
interface A <T> {
arr:T[]
value:T
}
class B implements A<number>{
arr:number[]
value: number
}
使用例子:
interface IbaseCRUD <T> {
data: T[]
add: (t: T) => void
getById: (id: number) => T
}
class User {
id?: number; //id主键自增
name: string; //姓名
age: number; //年龄
constructor (name, age) {
this.name = name
this.age = age
}
}
class UserCRUD implements IbaseCRUD <User> {
data: User[] = []
add(user: User): void {
user = {...user, id: Date.now()}
this.data.push(user)
console.log('保存user', user.id)
}
getById(id: number): User {
return this.data.find(item => item.id===id)
}
}
const userCRUD = new UserCRUD()
userCRUD.add(new User('tom', 12))
userCRUD.add(new User('tom2', 13))
console.log(userCRUD.data)
class A <T> {
default:T
add:(x:T,y:T) => T
}
const a = new A<number>()
a.default = 1
a.add = (x:number,y:number) =>{
return x + y
}
const b = new A<string>()
b.default = '1'
b.add = (x:string,y:string) =>{
return x + y
}
function fn <T>(x: T): void {
console.log(x.length) // 报错
}
这时需要一个规则来约束这个泛型T ,让他可以使用length属性
interface B {
length:number
}
function fn <T extends B>(x: T): void {
console.log(x.length) // 报错
}
注意:泛型约束中的extends意义上和实现相同,指T必须拥有接口B中的属性和方法
interface B {
length:number,
add:(a:number,b:number)=>number
}
function fn <T extends B>(x: T): void {
console.log(x.length)
console.log(x.add(100,200));
}
class C implements B{
length: number
add: (a: number, b: number) => number
}
fn<C>(
{
length:2,
add:(x,y)=>{
return x+y
}
}
)
keyof
interface Foo {
name: string;
age: number
}
type T = keyof Foo // -> "name" | "age"
const a : T = "name"
const b : T = "age"
type A = keyof any // type A = string | number | symbol
in
type Keys = "a" | "b"
type Obj = {
[p in Keys]: any
} // -> { a: any, b: any }
const a : Obj ={
a:'123',
b:123
}
infer
type A<T> = T extends (x: any) => infer P ? P : T;
type B = (x:number)=>number
const a : A<string> = '123'
const b : A<B> = 2
type myPartial<T> = { [P in keyof T]?: T[P] };
interface A {
a:string
b:string
}
const a: myPartial<A> = {
a:'132',
// b:'123'
}
type myRequired<T> = { [P in keyof T]-?: T[P] }
interface A {
name:string
age:number
addr?:string
}
const a : myRequired<A> ={
name:'zza',
age:26,
addr:'qewr'
}
type myRecord<K extends keyof any, T> = { [P in K]: T };
const a : myRecord<string,number> = {
// name:'zza', 报错
age:26
}
type myPick<T, K extends keyof T> = { [P in K]: T[P] };
interface A {
name:string,
age:number,
addr:string
}
type B = 'name' | 'age'
const a : myPick<A,B> = {
name:'zza',
age:26
}
type myReturnType<T> = T extends (...args: any[]) => infer R ? R: T;
type B = (x:number)=>number
const a : myReturnType<string> = '123'
const b : myReturnType<B> = 2