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[&lt;any&gt;"Happy"] 也不起作用 - “类型 'string' 不可分配给类型 'State'” @AlexOkrushko 不幸的是,在这种情况下,它似乎需要两边都有一个any 类型,就像我在这里所做的if(&lt;any&gt;this.gravity === GravityType[&lt;any&gt;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接口类型的主要内容,如果未能解决你的问题,请参考以下文章

typeScrip泛型

使用字符串类型参数访问枚举时出现 TypeScript TS7015 错误

TypeScriptTS进阶-函数重载

探索typescript的必经之路-----接口(interface)

typeScrip 类

typeScript入门接口