TypeScript 字符串与其索引没有关联的已知键,

xam8gpfp  于 4个月前  发布在  TypeScript
关注(0)|答案(5)|浏览(54)

TypeScript版本: 夜间版

代码:

{
const t: 't' = ("test" as const)[0];
}
{
const t: 't' = ([ 't', 'e', 's', 't' ] as const)[0];
}

预期行为:

当对字符串字面量进行索引时,TypeScript应该关联相应的键和值。

实际行为:

TypeScript将字符串中的所有索引类型设置为 string
TypeScript允许对字符串字面量的越界索引。

**链接:**https://www.typescriptlang.org/play?esModuleInterop=false&experimentalDecorators=false&emitDecoratorMetadata=false&ts=4.1.0-insiders.20201010#code/PTAEBcFMGdwLlAIirRBuCBPADpAJqAIbSgDukANhUSdgPbTQCWARhZKEwHagAqAygBpQAYzoBbbOygVMnceICu4Qmw6EuBANZc6pHoXCiJ2JuwhNxkAFBiusCDCMBeJCnCIax++DTXrIKDQABZ0ihQELByQAI6KTABuhOxcRuB0oAAUAE6QhHh0XLKgANqgAOTg5cLlkNUV0PWV5aAAugCU-nYO8BVVoK7uJQAMrX62hdB07AB0FHQA5pkuzq7N7RiBAGbJ0JDCduDZhNly6WTBhnz8oFEUTJAJMF2TRiKX2Qiw2dwLA46wEoAVjGL3s00gc0WyxwkDoW1EHwGqyQ31+iA2oG2u323iOJzOGVIlyMAlulAeT2g-gA3tZQAzvD0nP8ys0anUao0av1Wl5ur5-IymWkEM1-kNRn4AL5AA

相关问题:#19846

字符串,特别是字符串字面量,在索引时应该可以与字符数组进行比较。
当访问一个字符串 "foo" 时,其类型应该可以与索引 readonly [ 'f', 'o', 'o' ] 进行比较,尤其是考虑到JavaScript字符串是完全不可变的。
我怀疑没有人会反对知道长度,例如: const length: 4 = "test".length;

m2xkgtsf

m2xkgtsf1#

我有一个旧的PR关于这个:#19846

ui7jx7zq

ui7jx7zq2#

我之前有一个旧的PR关于这个:#19846
哦,我可能没有搜索得足够好,把那个添加到"相关问题"里,不过现在这看起来像是一个重复的问题:/

zqdjd7g9

zqdjd7g93#

在什么情况下会用到这个?

watbbzwu

watbbzwu4#

何时会用到这个功能?

这可以分为两个不同的部分:
安全性:
它和在字符数组上使用 as const 是一样的安全。怎么会出错呢?字符串是不可变的,所以它们应该总是 as const 。知道每个索引处的确切字符只能有所帮助。我不确定它的用途是什么,但它们应该与对比的等效物:字符数组完全一致。这是一个非常小的领域,但它确实有其存在的意义。我个人正在开发一个数据压缩/解压缩算法,无论我是否应该这样做,我都索引到了一个“已知”的字符串,并期望得到“已知”的结果,最坏的情况下,是字符串中字符的并集,但结果却是 string

错误:
目前所有的数值访问都会产生 string 。最近有一个配置标志提供了对数组上的更悲观的索引。我并不是建议我们在这里将它默认设置为这样,但是安全问题,正如我们所知,是非常重要的。问题在于所有的索引都会返回字符串,无论这些键是“安全”还是“不安全”的键。当你把字符串看作是字符元组而不是字符数组时,这个问题就更加严重了,这就是我建议的方式。显然像 "foo"[-1] 这样的东西是完全错误的,永远不应该出现在任何人的代码库中。希望 TypeScript 能在未来帮助防止这种情况的发生。

x7rlezfr

x7rlezfr5#

何时会用到这个特性?
A question on Stack Overflow :对于这个属性,它将是最明显、最清晰的解决方案:提取字符串字面量的首字符。可以使用 S extends${infer H}${string}? H : never 来实现,但这是一个非常不明显的方法,更复杂,而且文档中没有很好地说明(PR解释了这种行为,但它不在文档中)。此外,到达不是第一个字符的字符会很快变得相当烦人:你要么必须使用 ${string}${string}${infer Char2}${string}[2] 硬编码每个索引,要么你必须使用类似

type NthCharOf<S extends string, N extends number> =
  string extends S ? string :
  number extends S ? EachCharOf<S> :
  S extends `${infer H}${infer T}`
    ? [N, 0] extends [0, N]
      ? H
      : NthCharOf<T, Decrement<N>>
    : undefined;

type EachCharOf<S extends string, A extends string = never> =
  string extends S ? string :
  S extends `${infer H}${infer T}`
    ? EachCharOf<T, A | H>
    : never;

type Decrement<N extends number> =
  TupleOfLengthN<N> extends [unknown, ...infer T] ? T['length'] : number;

type TupleOfLengthN<N extends number, T extends unknown[] = []> =
  [N, T['length']] extends [T['length'], N] ? T :
  TupleOfLengthN<N, [...N, unknown]>;

相关问题