基础类型
(简单基础类型)原始类型: number string boolean symbol bigint undefined null
复杂基础类型:数组 Array,元组 Tuple,any ,void ,unknown,never ,object
布尔类型 boolean
boolean类型的值一般有两种 true 和false
let flag:boolean = false
let isShow:boolean = '123' //2322
new Boolean 是构造函数的实力 不是 boolean类型
let isDo:boolean = new Boolean() //2322
//返回的是一个 Boolean对象
let createByBoolean:Boolean = new Boolean() //Boolean
//直接调用 Boolean()的是 boolean类型
let bool:boolean = Boolean(1) //boolean
//在ts中其他基本类型的构造函数(除了null和undefined)以外都一样
let num:number = new Number(1) //2322
let Num:Number = new Number(1) //Number
let str:string = new String('123') //2322
let Str:String = new String('123') //String
数字类型 number
TS和JS一样,使用 number类型表示 十进制整数,浮点数,二进制数,八进制数,十六进制数
//十进制整数
let integer:number = 19
let integer1:number = Number(4)
//浮点数
let decimal:number = 3.4
/** 二进制整数 */
let binary: number = 0b1010;
/** 八进制整数 */
let octal: number = 0o744;
/** 十六进制整数 */
let hex: number = 0xf00d;
//使用较少的大整数,那么我们可以使用bigint类型来表示
let big:bigint = 100n
number 和 bigint虽然都表示数字,但是二者类型不兼容
big = integer
integer = big
类型检测会报2322 错误
let num:number = 123
let num1:number = '123' //2322
let anything:any
let num2:number = anything //可以给变量赋值anything类型变量值
let unknow: unknow
let num3:number = unknow //2322
let num4:number = null //2322
let num5:number = undefined //2322 严格模式下会报2322
let v:void
let n6:number = v //2322
let v1:void = unddefined
let v2:void = null //2322
字符串类型 string
let str:string = 'string' //字符串字面量
let str1:string = String('asd') //显式类型转换
let str11:string = String(123) //显示类型转换
let str2:string = 123 //2322 不能赋值其他类型值,除了any类型
//可以使用模版字符串,它可以定义多行文本和内嵌表达式。
//这种字符串是被反引号包围( `),并且以${ expr }这种形式嵌入表达式
let name:string = 'jack'
let age:number = 123
let str3:string = `name is:${name},age is:${age+1}`
let str4:string = 'name is:'+ name + 'age is:' + (age+1)
数组类型 array
多种方式定义数组类型
【类型+[] 】表示法 number[] 只寻允许数组元素是同一类型的
let arr1:number[] = [1,2,3]
let arr11:number[] = ['1',3,4] //报错
// Type 'string' is not assignable to type 'number'.
let numOfArr: number[] = [1, 2, 3, 4]
let strOfArr: string[] = ['a', 'b', 'c']
let boolOfArr: boolean[] = [true, false]
//不允许有其他类型
let a: any[] = []
a = [1, null, undefined, '123']
数组的一些方法也会根据定义数组类型时的约定来进行限制
let arr:number = [1,32]
arr.push('4')
// Argument of type '"4"' is not assignable to parameter of type 'number'.
使用数组泛型表示
会造成与JSX的语法冲突,尽量避免使用
let arr:Array<number> = [1,2,3]
//会造成与JSX的语法冲突,尽量避免使用
let arr2: Array<any> = []
使用接口表示数组
interface StringArray {
[index:number]:string
}
//StringArray 表示:只要索引的类型是数字时,那么值的类型必须是字符串。
//虽然接口也可以用来描述数组,但是我们一般不会这么做,因为这种方式比前两种方式复杂多了。
let strOfArr:StringArray = [1,2,3]
//TS2451: Cannot redeclare block-scoped variable 'strOfArr'.
let strOfArr1:StringArray = ['123','asd']
定义指定对象成员的数组,数组元素里面是对象
interface ArrObj{
name:string
age:number
}
const arr:ArrObj[] = [{name:'masr',age:23}]
定义联合类型数组
//联合类型值可以是字符串或者 是number元素类型的数组
let add:string|number[];
add = [1,2]
add = ['1','qwe',3] //不匹配 报错
add = '11231'
// 联合类型 数组成员可以是 字符串或者数字,其他元素类型不可以
let add1:(string|number)[];
add1 = [1,'s',2]
add1 = [1,2]
add1 = ['a','b']
add1 = ['a','b',null] //报错
add1 = '1231asd' //报错
//TS2322: Type 'string' is not assignable to type '(string | number)[]'.
元组类型Tuple
明确限制数组元素的个数和类型,元素类型不一定相同
//直接对元组初始化时候 需要满足元组类型定义的所有元素
let tup:[number,string]
tup = [1,'3']
tup = ['d','1] //报错,不匹配
tup = [1,'2',2] //报错
//也可以赋值其中一项
let tup1:[number,string]
tup1[1] = 'abc'
//访问一个已知元组元素索引时 会得到正确的类型
let tup2:[string,number]
tup2[0] = 'tom'
tup2[1] = 123
tup2[0].slice(1)
tup2[1].toFixed(2)
//当添加越界元素时候,所添加的元素类型会被限制被元组中每个类型的联合类型
let tup = [string,number]
tup.push(1) //ok
tup.push('a') //ok
tup.push(null) //error
//与联合类型数组相比较
let unionArr:(number|string|null)[] = [1,'d',null,23]
//联合类型数组与元组 相比较:
//联合类型数组不限制 元素个数和顺序
//元组在初始化的会严格限制元素的类型 和顺序
any 任意值
any是任意类型,拥有可以避过静态类型检测的特点。声明的any类型可以为其赋值任意类型。
可以对any 类型的变量进行任何操作,比如获取可能不存在的属性,方法等,且Ts无法检测是否存在,是否正确。
可以把任何类型的值,赋值给any类型的变量,也可以把any类型的值赋值给任何类型的变量
let anything:any = {}
anything.toFiexd(1) //ok
anything.doAnything() //ok
anything = 1 //ok
anything = 'qw' //ok
let str:string = anything //ok
let num:number = anything //ok
let numArr:number[] = anything //ok
//any类型成员的数组
let anyArr:any[] = [1,'qwe',null,undefined]
any类型在对象的调用链中会进行传导,所有any类型的任意属性的类型也是any
声明一个变量为任意类型后,对这个变量操作的属性,方法。返回的值都是任意类型
let anything:any
let c = anything.x.c //类型也是any
声明 的变量如果未指定类型,那么默认会是 any 类型
let anyth
anyth = 12
anyth = 'asd'
anyth = null
any类型与Object类型变量的区别
声明Object类型的变量也可以给该变量赋任意类型的值,但不能对其调用方法,即使该变量真的有此方法
let anyth:any = 4
anhty.toFixed(2) //ok
let obj:Object = 4 //ok
obj.toFixed(2) //error
// Error: Property 'toFixed' doesn't exist on type 'Object'.
unknown
Ts3.0添加类型,用来描述不确定类型的变量
可以给unknown 类型的变量赋值任意类型的值,但是unknown类型的值只能赋值给 unknown 或any 类型的变量
let ukn:unknown
ukn = 123 //ok
ukn = 'asd' //ok
let anyth:any = ukn //ok
let ukn1:unknown = ukn //ok
let num:number = ukn //error 2322
let str:string = ukn //error 2322
Ts会对unknown类型的变量做类型检测
需要对unknown类型的变量做类型缩小处理(类型条件判断),该unknown类型的变量操作方法时候才不会报错
let ukno:unknown
ukno.toFixed(2) //2571
ukno.toString() //2571
//不确定 unknown具体类型操作方法时会报错
//对unknown 类型进行变量缩小,不会提示错误
if (typeof ukn ==='string'){
ukn.toUpperCase() //string
}
if (typeof ukn ==='number'){
ukn.toFixed(2) //number
}
可以在多个 if else 条件分支下,使用unknown作为临时变量来接受不同条件下变量为类型各异的返回值。
let result: unknown;
if (x) {
result = x();
} else if (y) {
result = y();
} ...
void类型
使用于表示没有返回值的函数,如果一个函数没有返回值,它的类型就是void。
never类型
表示永远不会发生值的类型
function throwErr(msg:string):nerver{
throw Error(msg);
}
类型断言
清楚知道一个实体具有比他先有类型更确切的类型,类型断言来手动指定该值的类型,类型断言只在编译阶段起作用,不在运行时影响。
类型断言的两种方式
//值 as 类型
let someVal:any = 'this is a string'
let strLength:number = (someVal as string).length
let strLen1:number = someVal.length
//<类型>值
let someVal1:any = 'this is a string'
let strLength1:number = (<string>someVal1).length
当你在TypeScript里使用JSX时,只有 as 语法断言是被允许的,类型断言能够欺骗TS编译阶段,却在运行时程序依然会出错,所以请谨慎使用类型断言
类型断言的作用
将一个联合类型断言为其中一个类型
//TS 不确定一个联合类型的变量到底是什么类型时候,只能访问该联合类型的共有属性和方法
interface Cat {
name: string
run(): void
}
interface Fish {
name: string
swim(): void
}
function getName(animal: Cat | Fish) {
return animal.name
}
如果确实需要访问其中一个类型的方法或者属性的时候
function isFish(animal: Cat | Fish) {
if (typeof animal.swim === 'function') {
return true
}
return false
}
//TS2339: Property 'swim' does not exist on type 'Cat | Fish'.
//Property 'swim' does not exist on type 'Cat'.
//不确定animal的类型是Cat 还是Fish 所以想要直接访问Fish的swim方法会报错
//这时候可以使用类型断言,将animal的断言成为Fish,在编译阶段 如果animal的类型是 Fish即拥有swim方法 那么不会报错
//如果animal的类型不是Fish,没有swim方法,程序执行时候依然会报错
function isFish1(animal: Cat | Fish) {
if (typeof (animal as Fish).swim === 'function') {
return true
}
return fasle
}
{
let arr: number[] = [1, 2, 3, 4, 5]
let _item: number = arr.find(num => num > 2)
let _item1:number = arr.find(num=>num>2) as number //值 as 类型
//arr.find(num=>num>2) 返回值有可能是undefined 或者number 不确定返回类型,
//断言为numbe类型,编译阶段不会报错。
}
interface Cat {
name:string
run():void
}
interface Fish {
name:string
swim():string
}
function swim(animal:Cat|Fish) {
(animal as Fish).swim()
}
const tom:Cat = {
name:'Tom',
run(){console.log('run')}
}
swim(tom)
//编译不会报错,运行时候会报错,(animal as Fish).swim()隐藏了 animal有可能成为 Cat
将一个父类断言为更加具体的子类
class ApiError extends Error{
code:number = 0;
}
function isApiError(error:Error) {
if (typeof (error as ApiError).code === 'number'){
return true
}
return false
}
将任何一个类型断言为any
//当引用一个此类型上不存在的属性和方法的时候,会报错
{
let num:number =1
num.length = 1
}
//number类型不存在 length属性
//有时候确定代码不会报错,可以将类型断言为any
window.foo = 1 //ts 编译检测 window 不存在foo 会报错提示
(window as any).foo =1 //断言为any类型,any类型的变量访问任何属性和方法都是允许的
将any类型断言为一个具体的类型
//将any断言为一个具体类型 ,在处理 any 类型的变量中,比如第三方库未能定义好自己的类型,或者别人遗留的代码未能确定类型
// 可以通过类型断言 把any类型 断言为精确的类型 提高代码的可维护性
//方法返回值是any,可以在调用它之后将返回值断言成一个精确的类型,方便后续的操作
function getCacheData(key:string):any {
return (window as any).cache[key]
}
interface Cat {
name:string
run():void
}
{
let tom = getCacheData('Tom') as Cat
tom.run()
}
类型断言的限制
- 联合类型可以被断言为其中一个类型
- 父类可以被断言为一个子类
- 任何类型都可以被断言为any
- any可以被断言为任何类型
- A 兼容 B ,则 A可以被断言为B,B也可以被断言为 A
//Animal和Cat 都有name属性,Animal没有run()方法, 所以 Animal 兼容了 Cat
{
interface Animal {
name:string
}
interface Cat {name:string
run():void
}
function testCat(animal:Cat) {
return (animal as Animal)
}
function testAnimal(animal:Animal) {
return (animal as Cat)
}
}
双重断言
任何类型可以被断言为any
any可以被断言为任何类型
可以使用 as any as 类型 将任何一个类型断言为另一个任何类型
interface Cat {
run():void
}
interface Fish {
swim():void
}
function testCat(cat:Cat) {
return (cat as any as Fish);
}
//双重断言容易出错,迫不得已千万不用
类型断言 vs 类型转换
类型断言只会影响 TypeScript 编译时的类型,类型断言语句在编译结果中会被删除:
function toBoolean(something: any): boolean {
return something as boolean;
}
toBoolean(1);
// 返回值为 1
//代码在编译后会变成
function toBoolean(something) {
return something;
}
toBoolean(1);
// 返回值为 1
所以类型断言不是类型转换,它不会真的影响到变量的类型。
若要进行类型转换,需要直接调用类型转换的方法:
function toBoolean(something: any): boolean {
return Boolean(something);
}
toBoolean(1);
// 返回值为 true
类型断言 vs 类型声明/泛型
function getCacheData(key:string):any {
return (window as any).cache[key]
}
interface Cat {
name:string
run():void
}
//类型断言
let tom = getCacheData('tom') as Cat
tom.run()
//类型声明
let tom:Cat = getCacheData('tom')
//泛型
function getCacheData<T>(key:string):T {
return (window as any).cache[key]
}
let tom = getCacheData<Cat>('tom')
//更加规范的实现对 getCacheData 返回值的约束,这也同时去除掉了代码中的 any,是最优的一个解决
类型推论
变量如果没有明确指出类型,TS会根据类型推论的规则推断出一个类型
let num = 3
//这种推断发生在初始化变量和成员,函数默认参数,和函数决定返回值的时候
let str = 'string'
str = 7 //2322
//实际等价于
let str:string = 'string'
str = 7
//变量如果声明了没有赋值,会默认推论为any 类型
let num
num = 'str'
num = 7 //不会报错
函数类型
函数声明
//函数声明
function f3(x,y) {
return x+y
}
//函数表达式,函数字面量声明
const f4 = (x,y)=>{
return x+y
}
const f5 = function (x,y) {
return x+y
}
一个函数有输入(参数)和输出(返回值),Ts需要把参数和返回值都要考虑到
function f6(x:number,y:number):number {
return x+y; //number
}
实际参数多余或者少于形参都会报错提示
function f7(x:number,y:number):number {
return x+y;
}
f7(1,2,3) //error
f7(1) //error
函数表达式
const f4 = (x,y)=>{
return x+y
}
const f5 = function (x,y) {
return x+y
}
//一个函数有输入(参数)和输出(返回值),Ts需要把参数和返回值都要考虑到
function f6(x:number,y:number):number {
return x+y; //number
}
//实际参数多余或者少于形参都会报错提示
function f7(x:number,y:number):number {
return x+y;
}
f7(1,2,3) //error
f7(1) //error
//函数表达式
let sum = function (x:number,y:number):number {
return x+y
}
//以上代码只是对等号右侧对匿名函数做了类型定义,等号左边对变量是通过类型推论而推断出来对类型
//如果需要手动给等号左边对变量进行类型定义
let sum1:(x:number,y:number)=>number = (x:number,y:number)=>{
return x+y;
}
//Ts的箭头函数 区别于 ES6的箭头函数,TS的=>表示函数的定义,左边是输入类型,右边是输出类型
使用接口定义函数
采用函数表达式|接口定义函数的方式时,对等号左侧进行类型限制,可以保证以后对函数名赋值时保证参数个数、参数类型、返回值类型不变。
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function (source: string, subString: string) {
return source.search(subString) !== -1
}
let search1: SearchFunc = function (a, b) {
return a.search(b) === 1
}
可选参数
有时候参数不是必传项,利用?表示可选的参数
function f8(f:string,l?:string) {
if (l){
return f+l;
}
else{
return f
}
}
let funk = f8('f','l')
let funl = f8('f')
可选参数后面不允许再出现必选参数
参数默认值
function buildName(firstName: string, lastName: string = 'Cat') {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
在 ES6 中,我们允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数:
此时就不受「可选参数必须接在必需参数后面」的限制了:
function buildName(firstName: string = 'Tom', lastName: string) {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');
剩余参数
可以使用 ...rest 的方式获取函数中的剩余参数(rest 参数):
function push(array, ...items) {
items.forEach(function(item) {
array.push(item);
});
}
let a: any[] = [];
push(a, 1, 2, 3);
事实上,items 是一个数组。所以我们可以用数组的类型来定义它:
function push(arr:any[],...items:any[]){
items.forEach(item=>{
arr.push(item)
})
}
let a = []
push(a,1,2,3,4)
注意,rest 参数只能是最后一个参数
函数this
Js里 ,this的值在函数被调用的时候才能确定,需要搞清楚 函数调用的上下文
尤其在是返回一个函数或者将函数当作参数调用的时候。
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCradPicker: function () {
return function () {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
let cradPicker = deck.createCradPicker();
let pickedCrad = cradPicker(); //调用了返回的函数, 已经是独立的函数,
// 此时里面this指向了window而不是deck对象了,在严格模式下,this此时为 undefined而不是window
alert('card' + pickedCrad.card + 'of' + pickedCrad.suit);
//执行程序会报错 顶级的非方法式调用会将this视为window
为了解决该问题,可以在函数被返回时候绑定好正确的this,后面无论怎么使用它,都会引用绑定好的'deck'
对象,ES6箭头函数能保存函数创建时候的this的值,而不是调用的值
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCradPicker: function () {
//箭头函数 可以在这个返回函数创建时候 保存this的值,此时为deck
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
更好事情是,TypeScript会警告你犯了一个错误,如果你给编译器设置了--noImplicitThis标记。
它会指出 this.suits[pickedSuit]里的this的类型为any。
this.suits[pickedSuit]的类型依旧为any。 这是因为 this来自对象字面量里的函数表达式。
修改的方法是,提供一个显式的 this参数。 this参数是个假的参数,它出现在参数列表的最前面:
function f9(this) { //TS7006: Parameter 'this' implicitly has an 'any' type.
//this 的类型是any 发出警告
}
function f10(this: void) { //提供一个显式的 this参数 假的参数
}
增加接口类型,类型重用变得清晰简单
interface Card {
suit: string;
card: number;
}
interface Deck {
suits: string[];
card: number[];
createCradPicker(this: Deck): () => Card
}
let deck:Deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCradPicker: function (this:Deck) {
//箭头函数 可以在这个返回函数创建时候 保存this的值,此时为deck
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
alert("card: " + pickedCard.card + " of " + pickedCard.suit);
/*现在TypeScript知道createCardPicker期望在某个Deck对象上调用。
也就是说 this是Deck类型的,而非any,因此--noImplicitThis不会报错了。*/
this 在函数被调用时候才能确定值,指向谁
箭头函数在函数创建时候可以保存this,调用时候不改变this初始的引用对象
this 使用后或者当参数 是any 类型,可以指定一个假参数void,或者明确调用的类型,接口类型
this 参数在回调函数里
你可以也看到过在回调函数里的this报错,当你将一个函数传递到某个库函数里稍后会被调用时。 因为当回调被调用的时候,它们会被当成一个普通函数调用, this将为undefined。 稍做改动,你就可以通过 this参数来避免错误。 首先,库函数的作者要指定 this的类型:
interface UIElement {
addClickListener(onclick: (this: void, e: Event) => void): void;
}
this: void means that addClickListener expects onclick to be a function that does not require a this type. Second, annotate your calling code with this:
class Handler {
info: string;
onClickBad(this: Handler, e: Event) {
// oops, used this here. using this callback would crash at runtime
this.info = e.message;
}
}
let h = new Handler();
uiElement.addClickListener(h.onClickBad); // error!
指定了this类型后,你显式声明onClickBad必须在Handler的实例上调用。 然后TypeScript会检测到 addClickListener要求函数带有this: void。 改变 this类型来修复这个错误:
class Handler {
info: string;
onClickGood(this: void, e: Event) {
// can't use this here because it's of type void!
console.log('clicked!');
}
}
let h = new Handler();
uiElement.addClickListener(h.onClickGood);
因为onClickGood指定了this类型为void,因此传递addClickListener是合法的。 当然了,这也意味着不能使用 this.info. 如果你两者都想要,你不得不使用箭头函数了:
class Handler {
info: string;
onClickGood = (e: Event) => { this.info = e.message }
}
这是可行的因为箭头函数不会捕获this,所以你总是可以把它们传给期望this: void的函数。 缺点是每个 Handler对象都会创建一个箭头函数。 另一方面,方法只会被创建一次,添加到 Handler的原型链上。 它们在不同 Handler对象间是共享的。
函数重载
Js是动态的语言,函数里根据传入不同类型的参数而返回不同类型的数据很常见
Ts定义了重载来为函数提供返回不同类型的数据
//函数reverse 反转 传入 number 123 输出 number 321,传入 'hello' 输出 'olleh'
function reverse(x:number|string):number|string|void {
if (typeof x ==='number'){
return Number(x.toString().split('').reverse().join(''))
}
else if (typeof x === 'string'){
return x.split('').reverse().join('')
}
}
let a = reverse(231) //a 类型为 number|string|void
//需要将输出的类型准确的
function reverse(x:number):number;
function reverse(x:string):string;
function reverse(x:number|string):number|string|void {
if (typeof x ==='number'){
return Number(x.toString().split('').reverse().join(''))
}
else if (typeof x === 'string'){
return x.split('').reverse().join('')
}
}
重复定义了多次函数 reverse,前几次都是函数定义,最后一次是函数实现
注意,TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。
对象的类型-接口类型
接口类型 可以对 类的一部分进行抽象,也可以对 对象的形状进行描述,接口首字母一般要大写。
interface Person {
name: string;
age: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
接口的形状 和变量要保持一致,多属性和少属性都会报错
interface IPerson {
name:string;
age?:number;
}
let tom:IPerson = {
name:'tom',
age:12,
gener:'male'
}
可选属性 ,可以存在也可以缺省
interface IPer{
name:string;
age?:number;
}
let suoni:IPer ={
name:'suoni'
}
只读属性,属性初始化一个值后,不能再次赋值修改该属性
interface IPer{
readonly id:string;
name:'suoni'
age?:number
}
let tony:IPer ={
id:'string',
name:'suoni',
age:12
}
tony.id = '123' //error
任意属性 ,确定属性和可选属性的必须是任意属性的子集 ,或者任意属性是他们的联合类型
interface IPer{
name:string
age?:number
[propsName:string]:string
}
let tony:IPer = {
name:'tony',
age:12,
gender:'male'
}
//TS2322: Type '{ name: string; age: number; gerner: string; }' is not assignable to type 'IPer'.
//Property 'age' is incompatible with index signature.
//Type 'number' is not assignable to type 'string'.
// 任意属性 gender 是字符串类型 number 不是他的子集 所以报错
//可以定义为any类型
interface IPer{
name:string
age?:number
[propsName:string]:any
}
//或者确定属性和可选的属性的联合类型
interface IPer{
name:string
age?:number
[propsName:string]:string|number
}
let tony:IPer = {
name:'tony',
age:12,
gerner:'male'
}
只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候
let tony :IPer = {
id:'123',
name:'tony'
}
tony.id = '3453'
//TS2540: Cannot assign to 'id' because it is a read-only property.
//再次赋值修改了ID 属性 报错
let tony :IPer = {
name:'tony',
age:12
}
//TS2741: Property 'id' is missing in type '{ name: string; age: number; }'
//but required in type 'IPer'.
//没有给ID属性初始化值
接口描述函数类型
interface SearchFun {
(source:string,substring:string):boolean
}
let mySearch123:SearchFun;
mySearch123 = function (source:string,substring:string) {
return source.search(substring) !== -1;
}