TypeScriptTS接口类型
Posted 不叫猫先生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScriptTS接口类型相关的知识,希望对你有一定的参考价值。
🐱个人主页:不叫猫先生
🙋♂️作者简介:前端领域新星创作者、华为云享专家、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀!
💫系列专栏:vue3从入门到精通、TypeScript从入门到实践
📝个人签名:不破不立
📢资料领取:前端进阶资料以及文中源码可以找我免费领取(文末有我wx)
目录
专栏介绍
TypeScript从入门到实践专栏是博主在学习和工作过程中的总结,内容会不断进行精进,实用性非常强,欢迎订阅哦,学会TS不迷路。
TS系列 | 标题 |
---|---|
基础篇 | TS入门(一) |
基础篇 | TS类型声明(二) |
基础篇 | TS接口类型(三) |
基础篇 | TS交叉类型&联合类型(四) |
基础篇 | TS类型断言(五) |
基础篇 | TS类型守卫(六) |
进阶篇 | TS函数重载(七) |
进阶篇 | TS泛型(八) |
进阶篇 | TS装饰器(九) |
接口类型
我们经常说道的接口比如后端写了一个接口给前端调用,接口包括地址、参数、请求方式等等,参数规定了传参的类型。而在TS中的接口的定义是什么呢?
顾名思义,它也是一种类型,和number、string、undefined等一样,约束使用者使用,主要是用来进一步定义对象中属性的类型。它是对行为模块的抽象,具体的行为是用类来实现。
使用
通过interface
来声明类的类型,使用时需要注意以下几点:
interface
声明的类的首字母大写,这是tslint
规范,当然不使用时tslint
规范,写成小写是不会报错,建议大写- 在声明变量时,变量的形状必须跟接口的形状保持一致,即变量的属性值的类型必须和声明的类的属性的类型保持一致,否则会报错,少写、多写都会报错。
- 可对属性设置联合类型
- 接口中声明的属性类型以分号隔开
interface Class
name: string;
time: number;
let info: Class =
name: 'typescript',
time: 2
设置联合类型,具体如下:
interface Class
name: string;
time: number | string;
let info: Class =
name: 'typescript',
time: '2'
错误示范:
- 多写属性
let info: Class =
name: 'typescript',
time: 2,
age:18
- 与声明的类的属性的类型不一致
let info: Class =
name: 'typescript',
time: '2',
- 少写属性
let info: Class =
name: 'typescript',
另外除了以上基础用法外,还可以设置接口属性只读、索引签名、可选属性、函数类型接口,具体如下:
(1)设置属性只读
我们在接口中属性前加readonly,表示该属性为只读,如果修改该属性的值话就会报错
interface Class
readonly name: string;
time: number;
let info: Class =
name: 'typescript',
time: 2
info.name = 'zhangsan';//Error
(2)设置索引签名
设置索引签名后,在对象数据中传入多余的属性,仍能够执行。具体使用是在接口中定义一个 [property:string]:any
,意思是定义了一个属性,属性的类型是字符串,属性值类型为任意。
interface Class
readonly name: string;
time: number;
[property:string]:any
let info: Class =
name: 'typescript',
time: 2,
age:19,
sex:'男'
因为设置了索引签名,故而此时并不会报错。
当property设置为number时,则该属性就变成了类数组,具体如下所示:
interface Class
[property:number]:any
let info: Class = ['one','two'];
//可以通过索引进行访问值,但是不能使用数组的方法,毕竟不是真正的数组
console.log(info[0])//one
(3)设置可选属性
设置可选只需要在接口中属性后加?
,则表示该属性要不要都无所谓
- 可选属性没有赋值的时候,则获取到为
undefined
- 可选方法需要先判断,再调用
interface Class
readonly name: string;
time: number;
age?:number;
func?():void;
let info: Class =
name: 'typescript',
time: 2,
age:19,
少写age
此时也不会报错,因为接口中设置了可选
let info: Class =
name: 'typescript',
time: 2
console.log(info.age)//undefined
console.log(info.func())//Error,不能直接调用
//先进行判断,再调用,因为可能未定义func
if(info.func) info.func()
(4)函数类型接口
我们也可以用接口来定义函数的参数和返回值。
interface Class
(numA:number,numB:number):number
let info: Class = (numA,numB)=>numA+numB
info(1,2)
info(1,'2')//Error
使用字符串类型参数访问枚举时出现 TypeScript TS7015 错误
【中文标题】使用字符串类型参数访问枚举时出现 TypeScript TS7015 错误【英文标题】:TypeScript TS7015 error when accessing an enum using a string type parameter 【发布时间】:2016-07-18 21:34:30 【问题描述】:我是 TypeScript 的新手,我不明白我需要做什么来修复生成 TS7015 错误的行(使用字符串变量引用枚举成员),因为紧随其后的行没有错误(引用使用字符串文字的枚举成员):
enum State
Happy = 0,
Sad = 1,
Drunk = 2
function Emote(enumKey:string)
console.log(State[enumKey]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
console.log(State["Happy"]); // no error
"noImplicitAny": true
设置在项目的tsconfig.json
中检测到错误
在项目的tsconfig.json
中设置"noImplictAny": false
未检测到错误
我正在编译 "ntypescript": "^1.201603060104.1"
我现在正在使用"tsc": "1.8.10"
进行编译
C:>npm install -g typescript
`-- typescript@1.8.10
验证安装:
C:\>tsc --version
Version 1.8.10
这是我的tsconfig.json
文件:
"compileOnSave": true,
"compilerOptions":
"target": "ES5",
"module": "System",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": true,
"noImplicitAny": true,
"sourceMap": true,
"mapRoot": "map/",
"diagnostics": true
,
"exclude": [
"node_modules",
"typings"
]
这是编译器的输出:
C:\>tsc
test.ts(8,17): error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
【问题讨论】:
您在寻找什么样的答案?您已经注意到将noImplicitAny
设置为false
会使错误消失...
我不想关闭 noImplicitAny 检查,而是想修复代码以使其通过 noImplicitAny 检查。但更重要的是,我不明白为什么第一个引用错误,第二个引用通过(从类型上讲,两个枚举引用的类型是相同的......或者他们真的不是,我只是错过了一些东西(可能很明显) )
您使用的是什么版本的打字稿?我没有得到该代码的隐式任何类型错误。
"noImplicitAny": true,版本 1.8.2,没有错误,State[enumKey]
ntypescript
看起来主要是为那些想直接使用 TypeScript 编译器 API 的人准备的。我想你想要typescript
...
【参考方案1】:
我怀疑这与 TS 1.8.x 在这些情况下对字符串文字的新支持有关。 TS 碰巧知道“Happy”是一个有效的字符串索引,但它不知道enumKey
是否会是。您可以通过将其转换为 <any>
来修复它,如下所示:
function Emote(enumKey:string)
console.log(State[enumKey]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
console.log(State["Melancholy"]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
console.log(State["Happy"]); // no error
console.log(State[<any>enumKey]); // no error
console.log(State[<any>"Melancholy"]); // no error
(顺便说一句,我认为这是新的:我无法在 1.8.9 中重现此错误,但一旦升级到 1.8.10,我就可以了。)
另外有趣的是,我本来希望这可以在没有错误的情况下工作,但事实并非如此:
function TypedEmote(enumKey:'Happy'|'Sad'|'Drunk')
console.log(State[enumKey]);
一定是关于我不理解的 TS 规范的某些内容,或者他们可能还没有解决这个问题。
【讨论】:
有趣的是,“Melancholy”也出现了错误——让我怀疑编译器推断出有一个(未命名的)派生类型的字符串,并且仅限于“Happy”、“Sad”和“醉” --- 也许我可以明确定义这样的类型并使用它...... @Neoheurist - 这或多或少是我在上面的TypedEmote()
方法中尝试使用 'Happy'|'Sad'|'Drunk'
类型所做的。就像我说的,是的,我认为它应该有效,但似乎没有。很想知道你是否能找到办法。
state: State = State[<any>"Happy"]
也不起作用 - “类型 'string' 不可分配给类型 'State'”
@AlexOkrushko 不幸的是,在这种情况下,它似乎需要两边都有一个any
类型,就像我在这里所做的if(<any>this.gravity === GravityType[<any>dir])
或者,看看Sharpiro's answer,它是一个bit 更优雅。【参考方案2】:
var stateName = "Happy"
var state = <State>parseInt(State[<any>stateName]);
为了让编译器满意,我必须这样做
【讨论】:
它有效,但它很丑......史蒂文的解决方案要好得多。 (但请注意,它只是 TS 2.1+,所以 YMMV)【参考方案3】:您可以使用编译器选项来防止此错误,而不会丢失整个严格的空检查
"suppressImplicitAnyIndexErrors": true
https://www.typescriptlang.org/tsconfig#suppressImplicitAnyIndexErrors
【讨论】:
【参考方案4】:如果您使用的是 TypeScript 2.1+,您可以将 enumKey
的类型更改为 keyof typeof State
,如下所示:
function Emote(enumKey: keyof typeof State) ...
或者,如果函数的输入需要是string
,则:
var state : State = State[enumKey as keyof typeof State];
解释:
因为enumKey
是任意的string
,TypeScript 不知道enumKey
是否是State
的成员的名称,所以会产生错误。 TypeScript 2.1 引入了 keyof
运算符,它返回一个类型的已知公共属性名称的联合。使用keyof
可以让我们断言该属性确实在目标对象中。
然而,当你创建一个枚举时,TypeScript 实际上会生成一个 type(通常是 number
的子类型)和一个 value(枚举对象)您可以在表达式中引用)。当您编写keyof State
时,您实际上将获得number
的文字属性名称的联合。要获取枚举对象的属性名称,您可以使用keyof typeof State
。
来源:
https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/enums.html#enums-at-compile-time
【讨论】:
我更喜欢这个,而不是我们必须提供 TS 好处的其他解决方案。使用这个public rateType: keyof typeof RegularTypeEnum | BlockedTypeEnum;
,任何人都可以理解该属性的可能值。谢谢。
你的回答太好了,应该在官方文档里。
我很欣赏这个答案,但令人恼火的是,类型安全总是想办法将非常简单明了的代码变成类型声明的混淆。
哇,这个答案对我有用,但看着这个让我头疼:State[enumKey as keyof typeof State]
以上是关于TypeScriptTS接口类型的主要内容,如果未能解决你的问题,请参考以下文章
使用字符串类型参数访问枚举时出现 TypeScript TS7015 错误