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 Sign

const 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Zebec APP:构建全面、广泛的流支付应用体系

目前&#xff0c;流支付协议 Zebec Protocol 基本明确了生态的整体轮廓&#xff0c;它包括由其社区推动的模块化 Layer3 构架的公链 Nautilus Chain、流支付应用 Zebec APP 以及 流支付薪酬工具 Zebec payroll 。其中&#xff0c;Zebec APP 是原有 Zebec Protocol 的主要部分&a…

无向图-已知根节点求高度

深搜板子题&#xff0c;无向图&#xff0c;加边加两个&#xff0c;dfs输入两个参数变量&#xff0c;一个是当前深搜节点&#xff0c;另一个是父节点&#xff08;避免重复搜索父节点&#xff09;&#xff0c;恢复现场 ///首先完成数组模拟邻接表#include<iostream> #incl…

re学习(27)攻防世界toddler_regs(字符串函数总结+交叉引用)

找不到main&#xff08;&#xff09;函数&#xff0c;查找字符串&#xff0c;发现特殊字符串 定位字符串出现的位置&#xff0c;反汇编出代码&#xff0c;进行分析“ flag{Xp0int_1s_n1c3_but_Xp0intJNU_is_we1rd} 总结 一.CP&#xff1a;shiftF12 展示所有的字符串; ctrlx查…

python高阶技巧

目录 设计模式 单例模式 具体用法 工厂模式 优点 闭包 案例 修改闭包外部变量 闭包优缺点 装饰器 装饰器原理 装饰器写法 递归 递归的调用过程 递归的优缺点 用递归计算阶乘 设计模式 含义&#xff1a;设计模式是一种编程套路&#xff0c;通过这种编程套路可…

Linux-centos花生壳实现内网穿透

Linux-centos花生壳实现内网穿透 官网教程 1.安装花生壳 下载网址 点击复制就可以复制下载命令了 wget "https://dl.oray.com/hsk/linux/phddns_5.2.0_amd64.rpm" -O phddns_5.2.0_amd64.rpm# 下载完成之后会多一个rpm文件 [rootlocalhost HuaSheng]# ls phddns_…

Java8 list多属性去重

大家好&#xff0c;我是三叔&#xff0c;很高兴这期又和大家见面了&#xff0c;一个奋斗在互联网的打工人。 在 Java 开发中&#xff0c;我们经常会面临对 List 中的对象属性去重的需求。然而&#xff0c;当需要根据多个属性来进行去重时&#xff0c;情况会稍微复杂一些。本篇…

nodejs+vue鲜花商城销售系统 uniapp网上花店 多商家 微信小程序67m8n

在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括鲜花销售微信小程序的网络应用&#xff0c;在外国各式各样的小程序已经是很普遍的方式&#xff0c;不过国内可能还处于起步阶段。鲜花销售微信小程序具有鲜花销售信息管理功能…

利用awk筛选给定时间范围内的日志

文章目录 筛选给定时间范围内的日志时间时间戳什么是时间戳&#xff1f; 系统时间 筛选日志时间示例简单示例mktime()函数是什么 进阶示例 筛选给定时间范围内的日志 时间 时间的表示方法&#xff1a; 时间戳系统时间&#xff08;年月日时间&#xff09; 时间戳 什么是时间…

Linux中安装Node

安装 先从 官方网站 下载安装包&#xff0c;有时 node 版本太新会导致失败&#xff0c;详见下方的常见问题第2点 cd /home // 创建目录&#xff0c;将下载好的 node 安装包上传到此目录 mkdir Download mkdir /usr/local/lib/node解压 // 解压&#xff0c;前面是文件当前路径…

Spring集成Junit

目录 1、简介 2、Junit存在的问题 3、回顾Junit注解 4、集成步骤 4.1、导入坐标 4.2、Runwith 4.3、ContextConfiguration 4.4、Autowired 4.5、Test 4.6、代码 5、补充说明 5.1、Runwith 5.2、BlockJUnit4ClassRunner 5.3、没有配置Runwith ⭐作者介绍&#xff1…

uniapp android底部弹框

uniapp android底部弹框&#xff0c;带有动画效果 <view class"popup_box"><view class"bottom_more" click"handleClickCancel"><image src"/static/images/rescue/icon_more.png"></image></view><…

C++笔记之从数组指针到函数数组指针(使用using name和std::function)

C笔记之从数组指针到函数数组指针(使用using name和std::function) 参考笔记&#xff1a; C之指针探究(三)&#xff1a;指针数组和数组指针 C之指针探究(十三)&#xff1a;函数指针数组 C之指针探究(二)&#xff1a;一级指针和一维数组 C之指针探究(十一)&#xff1a;函数名的…

C语言数组笔试题(详解)

目录 插入知识&#xff1a; 一.指向函数指针数组的指针 二.回调函数 什么是回调函数&#xff1f; 三.数组笔试题 个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生&#x1f43b;‍❄个人主页&#xff1a;GOTXX &#x1f4…

Jenkins工具系列 —— 插件 实现用户权限分配与管理

文章目录 安装插件 Role-based Authorization Strategy添加用户注册配置权限查看当前使用者&#xff0c;获取user id配置管理员权限配置普通用户权限&#xff08;非管理员权限&#xff09; 小知识 安装插件 Role-based Authorization Strategy 点击 左侧的 Manage Jenkins —&…

【PostgreSQL】系列之 一 用户创建和授权(三)

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,Java基础学习,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的…

Michael.W基于Foundry精读Openzeppelin第20期——EnumerableMap.sol

0. 版本 [openzeppelin]&#xff1a;v4.8.3&#xff0c;[forge-std]&#xff1a;v1.5.6 0.1 EnumerableMap.sol Github: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.3/contracts/utils/structs/EnumerableMap.sol EnumerableMap库提供了Bytes32ToB…

使用Python将图像转换为PDF:一次性解决您的批量转换需求

导语&#xff1a; 在数字化时代&#xff0c;我们经常需要处理大量的图像文件。将这些图像转换为PDF格式可以方便地存档、分享和打印。本文将介绍如何使用Python编程语言将图像批量转换为PDF&#xff0c;并提供了一个简单易用的图形界面来跟踪转换进度。 准备工作 在开始之前…

【雕爷学编程】MicroPython动手做(33)——物联网之天气预报

天气&#xff08;自然现象&#xff09; 是指某一个地区距离地表较近的大气层在短时间内的具体状态。而天气现象则是指发生在大气中的各种自然现象&#xff0c;即某瞬时内大气中各种气象要素&#xff08;如气温、气压、湿度、风、云、雾、雨、闪、雪、霜、雷、雹、霾等&#xff…

kibana-7.17.3版本安装及汉化

1、官网下载地址&#xff1a;https://www.elastic.co/cn/downloads/kibana 选择安装系统类型和历史版本kibana安装版本要和es版本对应 2、上传安装包然后解压 tar -zxf kibana-7.17.3-linux-x86_64.tar.gz 3、更改目录属主 chown elk. kibana-7.17.3-linux-x86_64 -R …

【QT调用ST-link-使用QT编写程序-调用ST-LINK_CLI.exe-烧写STM32F4xxx-基础样例】

【QT结合ST-link&#xff0c;使用QT编写程序&#xff0c;调用ST-LINK_CLI.exe,烧写STM32F4xxx-基础样例】 1、前言2、实验环境3、先前了解-自我总结4、实验过程&#xff08;0&#xff09;硬件连接与供电&#xff08;1&#xff09;安装&使用STM32 ST-LINK Utility&#xff0…