unkonw
任何数据的类型都是unkonw的子类型
所以unkonw只能作为类型的父类 ,不能作为类型的子类
implements extends
implements 理解为实现 A implement B, A上要有B对应的属性和方法
不能用于两个interface之间
类和类之间
*class* Son *implements* *Parent* {} *//用于类之间 此时没有继承的效果,而是要求Son上要有Father类定义的属性
和方法*
类和接口之间:
*class* Son *implements* *IParent*{}*//用接口去规范class,要求Son的属性和方法要按照IParent接口中定义的来*
在他typescript中使用implements来实现一些类共有方法属性的提取
// 接口
interface IPerson{
name:string
age:number
fn1:fnType
}
const zhangsan:IPerson = {
name:"张三",
age:20,
fn1(a:number,b:number){}
}
// class 类
class Person implements IPerson{
name:string
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
fn1(a:number,b:number):viod{}
}
ts中extends可以理解为es6 class对应的extends
可以实现类的继承 class Son extends Parent{}
可以实现接口的继承
*interface* ISon *extends* *IParent*{
sonValue:*number**//ISon上除了从IFather继承属性,还增加了sonValue*
}
泛型的extends属性
T extends object 是泛型约束的一种表现
而泛型约束简单点来说就是把泛型的具体化数据类型范围缩小
那上面就可以理解为具体的泛型类型只能是object类型
type和interface
就是对接口定义的两种不同方式,目的都是一样的,都是定义对象或者函数的形状
interface dog{
name:string
age:number
}
interface dogFun {
(name:string,age:number):void
}
type dog={
name:string
age:number
}
type dog = (name:string,age:number)=>void
也支持继承 并且不是独立的 而是可以互相继承,只是具体的形式稍有差别
type dogType = {
name:string
}
interface dogInterface{
name:string
}
type dogType2 = dogType &{
age:number
}
type dogInterface2 = dogInterface &{
age:number
}
interface dog2 extends dogType{
age:number
}
interface dog2 extends dogInterface{
age:number
}
对于interface来说 继承是通过extends实现的 而type的话是通过&来实现的,也可以叫做交叉类型
type和interface的不同点
1. type可以定义基本类型的别名:type myString = string
2. type可以通过typeof操作符来定义 type myString = typeof someObj
3. type 可以申明联合类型 如 type unionType = myType1|myType
4. type 可以申明元祖类型 如 type yuanzuArr = [type1,type2]
interface可以声明合并
interface test {
name:string
}
interface test {
age:number
}
如果是type,就会报重复定义的警告。
类
*面向对象:
通过extends实现继承
通过public等访问修饰符实现封装
通过方法覆盖实现多态*
注意事项:
私有private:当成员被标记成private时,它就不能在声明它的类的外部访问
保护protected:protected成员在派生类中仍然可以访问
只读readonly:只读属性必须在声明时或构造函数里被初始化
参数属性:给构造函数的参数加上修饰符 能够定义并初始化一个成员属性
class Animal {
constructor(private name:string){//定义name属性并将构造参赋值给他
}
}
存取器:当获取和设置属性时 有额外逻辑时可以使用存取器(又称getter,setter)
class Employee {
private _fullName: string = 'Mike James'
get fullName(): string {
return this._fullName
}
set fullName(newName: string){
console.log('你修改了用户名')
this._fullName = newName
}
}
// 类型注解
// let name1: string;
// name1 = 'tom'
// name1 = 123 wrong
let name1: string|object;
name1 = 'tom'
name1 = {name:'fe'}
// 类型推论
let name2 = 'jerry'
// 数组类型
let names: string[]
names=['qwe']
// 任意类型
let foo:any = 'xx'
foo = 123
// 任意类型也可用于数组
let list: any[] = [1,true,'free']
list[1] = 100
// 函数中的类型
// 同时设置了返回值类型
function greeting(person:string):string{
return 'hello'+ person
}
function greeting2(person: string): void {
}
greeting('tom')
//常见内置类型 void没有返回值
// string,number,boolean,void,any
//函数
// 此处name和age是必填参数
// 如果要变为可选参数 加上?
// 可选参数在必选参数的后面
function sayHello(name:string,age:number=20,addr?:string):string{
return '你好:'+ name + '' + age
}
sayHello('jerry')
sayHello('jerry', 36)
// 函数的重载:以参数数量或类型区分多个同名参数
// 如果一个函数,将来的参数的类型或者参数的个数,或者返回值的类型 如果不同,可以认为是另外一个重载,
// 它的函数的方法名可以是相同的
// 参数的数量或者类型或者返回值的类型不同, 函数名却相同
// 先声明 在实现
function info(a:{name:string}):string
function info(a:string):object
function info(a: {name:string}|string): any {
if (typeof a === "object"){
return a.name
} else {
return {name:a}
}
}
console.log(info({name:"tom"}))
console.log(info("tom"))
// Class面向对象
// class Shape {
// area: number
// protected color: string
// constructor(color:string,width:number,height:number){
// this.area = width*height
// this.color = color
// }
// shoutout(){
// return "I'm"+this.color+'width an area of'+this.area+'cm squared'
// }
// }
class Shape {
// area: number
// protected color: string
constructor(protected color: string, protected width: number, protected height: number) {
// this.area = width * height
this.color = color
}
// 类似于vue的计算属性 变相实现只读的属性
get area(){
return this.width*this.height
}
shoutout() {
return "I'm" + this.color + 'width an area of' + this.area + 'cm squared'
}
}
class Square extends Shape {
constructor(color: string, side: number){
super(color,side,side)
console.log(this.color)
}
// 覆盖
shoutout(){
return "我是"+this.color+"面积是"+this.area+"平方厘米"
}
}
const square= new Square('blue',2)
console.log(square.shoutout())
接口
接口仅约束结构,不要求实现 使用更简单
interface Person{
firstName:string,
lastName:string
}
function greeting(person:Person){
return 'Hello,'+ person.firstName+''+person.lastName
}
const user = {firstName: 'Jane',lastName: 'User'}
console.log(user)
console.log(greeting(user))
泛型
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型 而是在使用的时候再指定类型的一种特性
// 不使用泛型
interface Result {
ok:0|1;
data: Feature
}
// 使用泛型
interface Result<T> {
ok:0|1;
data:T[]
}
范例:使用泛型约束接口返回类型
function getData<T>(): Result<T> {
const data:any[] = [
{ id: 1, name: '3ere', version: '1.2' },
{ id: 2, name: 'fffff', version: '2.2' }
]
return {ok:1,data}
}
// 使用接口
created(){
this.features = getData<Feature>().data
}
装饰器
*装饰器实际上是工厂函数 传一个对象,输出处理后的新对象
典型应用是组件装饰器@Component*
@Component
export default class Hello extends Vue
若不加小括号,则装饰器下面紧挨着的对象就是目标对象
@Component({
props:{//属性也可以在这里配置
name:{
type:String,
default:'匿名'
}
}
})
export default class Hello extends Vue {}
类似的还有App.vue中配置的依赖组件选项components
范例: 事件处理@Emit
新增特性时派发事件通知父组件,Hello.vue
// 通知父类新增事件,若未指定事件名则函数名作为事件名(羊肉串形式)
@Emit()
private addFeature(event:any){
const feature = {name:event.target.value,id:this.features.length+1};
this.features.push(feature)
event.target.value = ""
return feature//返回值作为事件参数
}
父组件接收并处理 App.vue
<Hello @add-feature="onAddFeature"></Hello>
export default class App extends Vue{
private onAddFeature(feature:any) {
console.log("新增特性:"+feature.name)
}
}
范例:属性变更检测@Watch, sayHello.vue
//
@Watch('msg')
onRouteChange(val:string,oldVal:any){
console.log(val,oldVal)
}
在vue中的实际使用
在创建项目的时候选typeScript
App.vue
<template>
<div id="app">
<!-- <img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/> -->
<Hello msg="Welcome tottt Your Vue.js + TypeScript App" @add-feature="xxx"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';
import Hello from './components/Hello.vue';
@Component({
components: {
HelloWorld,
Hello
},
})
export default class App extends Vue {
xxx(){
}
}
</script>
<style>
</style>
组件Hello.vue
<template>
<div>
<div>
<input type="text" placeholder="输入新特性" @keyup.enter="addFeature">
</div>
{{msg}}
<ul>
<li v-for="feature in features" :key="feature.id">{{feature.name}}</li>
<li>{{count}}</li>
</ul>
</div>
</template>
<script lang="ts">
import {Component,Prop,Vue,Emit,Watch} from 'vue-property-decorator'
//接口中只需要定义结构 不需要初始化
interface Feature{
id:number;
name: string;
version:string
}
interface Result<T> {
ok:0|1;
data:T[]
}
function getData<T>(): Result<T> {
const data:any[] = [
{ id: 1, name: '3ere', version: '1.2' },
{ id: 2, name: 'fffff', version: '2.2' }
]
return {ok:1,data}
}
@Component({
props:{//属性也可以在这里配置
name:{
type:String,
default:'匿名'
}
}
})
export default class Hello extends Vue{
// 函数类型去使用的
// 类型控制 一个是用于vue编译器的 一个用于ts编译器
@Prop({required: true,type:String}) msg!: string;
// data中的值
// private features = ['类型注解','blabla']
// private features:Feature[] = [{id:1,name:'类型注解',version:'1.0'}]
private features!:Feature[];
@Watch('features',{deep:true})
onRouteChange(val:string,oldVal:any){
console.log(val,oldVal)
}
@Emit()
private addFeature(event:any){
const feature = {name:event.target.value,id:this.features.length+1,version:'1.0'}
this.features.push(feature)
event.target.value= feature
return event.target.value
}
// get count(){
// return this.features.length
// }
// 如果要让继承的类访问 protected
// 如果都能访问public
// 生命周期
private created(){
setTimeout(()=>{
this.features.push({id:2,name:'sss注解',version:'2.0'})
},1000)
// 约束返回的结果是Result类型 里面的data得是Feature类型 两层约束
// this.features = getData<Result<Feature>>().data
}
}
</script>
<style scoped>
</style>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。