Typescript - 索引签名

目录

  • 1,什么是索引签名
    • 1,js 中使用对象的属性
    • 2,ts 中的索引签名
    • 3,扩展索引签名定义的类型
  • 2,与 Record 对比
  • 3,遇到的问题
    • 1,索引 key 的类型问题,`keyof`
    • 2,索引 key 的类型问题2:受具体定义的影响

1,什么是索引签名

1,js 中使用对象的属性

在 js 中,访问对象的 key

let user = {name: "下雪天的夏风",19: "19value",
};console.log(user.name);
console.log(user[19]);
user.age = 18

如果key对象,会默认执行它的 toString() 方法。

let user = {name: "下雪天的夏风",
};
const obj = {toString() {console.log("be string");return "_obj";},
};user[obj] = "关注一波";
console.log(user);
// be string
// { name: '下雪天的夏风', _obj: '关注一波' }

其他的类型,来看下结果

let user = {};const obj1 = {toString() {console.log("be string");return "_obj";},
};
const obj2 = {};
function foo() {}
const sym = Symbol();user[obj1] = "obj1 的 value";
user[obj2] = "obj2 的 value";
user[foo] = "foo 的 value";
user[sym] = "sym 的 value";
console.log(user); // { name: '下雪天的夏风', _obj: '关注一波' }/* 
be string
{_obj: 'obj1 的 value','[object Object]': 'obj2 的 value','function foo() {}': 'foo 的 value',[Symbol()]: 'sym 的 value'
}
*/

可以看到,对象默认的 toString() 方法执行结果比较特殊。

2,ts 中的索引签名

可以简单的理解:key 就是索引

基于在 js 中对象和函数等作为索引产生的特殊行为,ts 做了进一步的约束。
索引类型只能是:string | number | symbol,而value 可以是任意类型

  1. 其中string 也可以是模板字面量
interface HandleEvents {[key: `${string}Changed`]: () => void;
}
  1. 对象如果想作为索引,必须显示的调用.toString() 方法
let user: any = {};const obj1 = {toString() {return "_obj1";},
};// Type '{ toString(): string; }' cannot be used as an index type.ts(2538)
user[obj1] = "obj1 的 value";
user[obj1.toString()] = "ok";

索引签名就是在约束了索引(key)类型的基础上,统一定义了对象的 keyvalue 的类型

换句话说,索引签名可以在只知道keyvalue 的类型下,来统一定义对象的类型

规定:当声明一个索引签名后,所有成员都必须符合索引签名:

举例:

interface Sign1 {// key 只是占位符,随便什么单词都可以[key: string]: string;
}type Sign2 = {[index: number]: string | number;
};const foo: {[aaa: string]: { message: string }; // value 只能是1个对象,并且只有1个属性 message
} = {};

3,扩展索引签名定义的类型

  1. 可同时指定已确定的类型
// 必须包含 x 属性
interface Sign1 {[key: string]: number;x: number;
}interface Sign2 {[key: string]: number;y: string; // Error: 属性 y 的类型只能是'number'.ts(2411)
}
  1. 多个索引签名

在多个索引签名存在时,string 类型的索引最严格,书写时应该包含所有的 value 类型(假设为 All)。
其他类型的索引,对应的 value 类型只能是 All 的子级。

interface Sign3 {[key: string]: string | number | boolean; // 必须包括所用成员类型[index: symbol]: string;[index2: number]: number;
}
  1. 扩展

即便使用多个索引签名,也有覆盖不到的情况。

比如定义的对象中有一个list:string[] 字段,其他字段都不是string[] 类型。如果按照下面的写法,任何字段都可以是string[] 类型

interface Sign4 {[key: string]: string | number | string[]; // 必须包括所用成员类型
}

我们可以用索引签名+联合类型。

type Sign4 = {[key: string]: string | number;
} | { list: string[] }

2,与 Record 对比

先看下 Record 的定义

// node_modules\typescript\lib\lib.es5.d.ts
type Record<K extends keyof any, T> = {[P in K]: T;
};

在这里插入图片描述

鼠标放上去之后,会发现其实 keyvalue的类型的规则和索引签名的一致,也是:string | number | symbol,而value 可以是任意类型。

所以,二者并没有多大的区别,只是使用上略有不同而已。目前只发现的一个区别:

Record 的 key 可以为具体的类型,一般用于创建具有特定键值对的对象类型。

type Type1 = Record<'a | b | c', string>

3,遇到的问题

1,索引 key 的类型问题,keyof

type Sign = {[key: string]: boolean;
}
// string | number
type keys = keyof Signconst obj: Sign = {};
obj[2] = 123; // ok
obj["3"] = 123;

原因是:当数字作为 key 时,js 会隐式地将数字强制转换为字符串,ts 也会执行这种转换。

2,索引 key 的类型问题2:受具体定义的影响

这是我的提问

<script setup lang="ts">
interface NumberDictionary {[index: string]: string;
}const formInfo: NumberDictionary = {name: "john",want: "eat",
};Object.entries(formInfo).forEach(([key, value]) => {console.log(key, value);
});
</script>
<template><form><input v-for="(value, key) in formInfo" :name="key" :value="value" :key="key" type="text" /></form>
</template>

可以看到2个地方 key 的类型不一致:

在这里插入图片描述
在这里插入图片描述

原因:

  1. Object.entries 的类型声明
// node_modules\typescript\lib\lib.es2017.object.d.ts
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];

可以看到接受的就是 string 类型,相当于在 forEach 使用时,key 已经被断言为 string 类型了。

  1. v-for 的类型声明
// node_modules\@vue\runtime-core\dist\runtime-core.d.ts  第 1602 行
/*** v-for object*/
export declare function renderList<T>(source: T, renderItem: <K extends keyof T>(value: T[K], key: K, index: number) => VNodeChild)
: VNodeChild[];

可以看到 K extends keyof T,很熟悉!这就是上面遇到的第1个问题。
对上面这个例子来说,v-forkey 的类型就是 string | number

知道原因了,解决方法就有了,用Record 即可

interface NumberDictionary {[index: string]: string;
}
// ↓↓
type NumberDictionary = Record<string, string>

以上。


参考

索引签名-参考1

索引签名-参考2

索引签名-参考3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/78971.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

烧结钕铁硼的物理性能

烧结钕铁硼永磁体作为核心功能部件&#xff0c;广泛应用在电机、电声、磁吸和传感器等仪器设备中。磁体在服役过程中&#xff0c;会受到机械力、冷热变化、交变电磁场等环境因素&#xff0c;如果发生环境失效&#xff0c;将会严重影响设备的功用&#xff0c;造成巨大的损失。因…

QT - 建立页面

一、生成页面 二、实现 1.LineEdit 是一个单行输入文本框&#xff0c;为用户提供了比较多的编辑功能&#xff0c;例如选择复制、粘贴。 修改echomode属性为password Push Button(常规按钮) 三、程序 声明全局变量&#xff0c;属于MainWindow private: // 定义了一个指向Ma…

24届近5年上海交通大学自动化考研院校分析

今天给大家带来的是上海交通大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、上海交通大学 学校简介 上海交通大学是我国历史最悠久、享誉海内外的高等学府之一&#xff0c;是教育部直属并与上海市共建的全国重点大学。经过120多年的不懈努力&#xff0c;上海交…

【Linux旅行记】第一个小程序“进度条“!

文章目录 一、预备知识1.1回车换行1.2缓冲区 二、倒计时三、进度条3.1普通版本源代码3.2高级版本源代码 &#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &…

Vue3自定义简单的Swiper滑动组件-触控板滑动鼠标滑动左右箭头滑动-demo

代码实现了一个基本的滑动功能&#xff0c;通过鼠标按下、鼠标松开和鼠标移动事件来监听滑动操作。 具体实现逻辑如下&#xff1a; 在 onMounted 钩子函数中&#xff0c;我们为滚动容器添加了三个事件监听器&#xff1a;mousedown 事件&#xff1a;当鼠标按下时&#xff0c;设置…

Netty面试题1

计算机网络模型 OSI采用了分层的结构化技术&#xff0c;共分七层&#xff0c; 物理层、数据链路层、网络层、传输层、会话层、表示层、应用层 。 Open System Interconnect 简称OSI&#xff0c;是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参…

超详情的开源知识库管理系统- mm-wiki的安装和使用

背景&#xff1a;最近公司需要一款可以记录公司内部文档信息&#xff0c;一些只是累计等&#xff0c;通过之前的经验积累&#xff0c;立马想到了 mm-wiki&#xff0c;然后就给公司搭建了一套&#xff0c;分享一下安装和使用说明&#xff1a; 当前市场上众多的优秀的文档系统百…

6.s081/6.1810(Fall 2022)Lab4: Traps

文章目录 前言其他篇章参考链接0. 环境搭建1. RISC-V assembly (easy)1.0 简介1.1 Q11.2 Q21.3 Q31.4 Q41.5 Q51.6 Q6 2. Backtrace (moderate)2.1 简单分析2.2 实现2.3 测试 3. Alarm (hard)3.1 简单分析3.2 test0: invoke handler3.2.1 添加调用3.2.2 获取参数3.2.3 处理中断…

服务器硬件、部署LNMP动态网站、部署wordpress、配置web与数据库服务分离、配置额外的web服务器

day01 day01项目实战目标单机安装基于LNMP结构的WordPress网站基本环境准备配置nginx配置数据库服务部署wordpressweb与数据库服务分离准备数据库服务器迁移数据库配置额外的web服务器 项目实战目标 主机名IP地址client01192.168.88.10/24web1192.168.88.11/24web2192.168.88…

Baumer工业相机堡盟工业相机如何通过BGAPISDK获取相机接口数据吞吐量(C++)

Baumer工业相机堡盟工业相机如何通过BGAPISDK里函数来获取相机当前数据吞吐量&#xff08;C&#xff09; Baumer工业相机Baumer工业相机的数据吞吐量的技术背景CameraExplorer如何查看相机吞吐量信息在BGAPI SDK里通过函数获取相机接口吞吐量 Baumer工业相机通过BGAPI SDK获取数…

STM32 CubeMX USB_(HID 鼠标和键盘)

STM32 CubeMX STM32 CubeMX USB_HID&#xff08;HID 鼠标和键盘&#xff09; STM32 CubeMX前言 《鼠标》一、STM32 CubeMX 设置USB时钟设置USB使能UBS功能选择 二、代码部分添加代码鼠标发送给PC的数据解析实验效果 《键盘》STM32 CubeMX 设置&#xff08;同上&#xff09;代码…

睡眠助手/白噪音/助眠夜曲微信小程序源码下载 附教程

睡眠助手/白噪音/助眠夜曲微信小程序源码 附教程 支持分享海报 支持暗黑模式 包含了音频数据 最近很火的助眠小程序&#xff0c;前端vue&#xff0c;可以打包H5&#xff0c;APP&#xff0c;小程序 后台可以设置流量主广告&#xff0c;非常不错的源码 代码完整 完美运营 搭配无…

Django实现音乐网站 ⑸

使用Python Django框架制作一个音乐网站&#xff0c; 本篇主要是配置媒体资源设置。 目录 配置介绍 设置媒体资源 创建媒体资源目录 修改settings.py 注册媒体资源路由 总结 配置介绍 静态资源是指项目配置的js/css/image等系统常用文件。对于一些经常变动的资源&#x…

LLM reasoners 入门实验 24点游戏

LLM reasoners Ber666/llm-reasoners 实验过程 实验样例24games&#xff0c;examples/tot_game24&#xff0c;在inference.py中配置使用代理和open ai的api key。 首先安装依赖 git clone https://github.com/Ber666/llm-reasoners cd llm-reasoners pip install -e .然后…

UltraToolBars Crack,动画菜单和多种显示样式

UltraToolBars Crack,动画菜单和多种显示样式 创建模仿Microsoft Office 2000外观的健壮应用程序。 UltraToolBars包括11个用于创建可自定义工具栏的界面增强控件&#xff0c;包括&#xff1a;个性化菜单、弹出型工具栏、集成选项卡控件等。PictureRegion技术使表单和组件能够采…

C# Blazor 学习笔记(0.1):如何开始Blazor和vs基本设置

文章目录 前言资源推荐环境如何开始Blazor个人推荐设置注释快捷键热重载设置 前言 Blazor简单来说就是微软提供的.NET 前端框架。使用 WebAssembly的“云浏览器”&#xff0c;集成了Vue,React,Angular等知名前端框架的特点。 资源推荐 微软官方文档 Blazor入门基础视频合集 …

张驰课堂:6西格玛绿带培训费用、内容及实施要点分析

6西格玛绿带培训是一种质量管理培训&#xff0c;旨在帮助企业提高质量和效率。这种培训通常由咨询公司或培训机构提供&#xff0c;费用因提供者而异。以下是一些有关6西格玛绿带培训费用和培训内容的信息。 6西格玛绿带培训费用取决于培训机构&#xff0c;还有培训的持续时间和…

【vue】初步使用element-ui框架

cd到当前项目&#xff0c;运行 cnpm i element-ui -S 接下来就是在项目里面引用了&#xff0c;打开src目录下的main.js //导入vue.js import Vue from vue //导入下面2个组件 import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css //导入App.vue根组…

Nginx可视化Nginx-gui

Github&#xff1a;GitHub - onlyGuo/nginx-gui: Nginx GUI Manager 运行方式支持docker、window 下载后压缩&#xff0c;直接运行startup.bat 默认账号密码&#xff1a;admin/admin

gin框架学习

文章目录 配置go环境实现一个简单的web响应服务验证功能gin增加页面以及传递数据 配置go环境 去go官网下载对应的版本 go下载地址 tar -C /usr/local -xzf go1.4.linux-amd64.tar.gz 我们可以编辑 ~/.bash_profile 或者 /etc/profile&#xff0c;并将以下命令添加该文件的末…