目前在TypeScript中是否有一种方法可以将两个或多个字符串文本类型连接成一个单独的字符串文本类型?

38

首先,让我明确一下,我想要的不是联合类型,而是简单的字符串拼接,即 "Hel" + "lo" = "Hello",但是针对字符串字面量类型。

实际上,我有一个函数,它接受两个字符串字面量作为参数,一个是 namespace,一个是 name,并以它们之间用 / 连接后的字符串作为输出,但是我无法找到一种方法将输出设置为字符串字面量而不是普通字符串。

我需要它成为一个字符串字面量,因为输出将被用作对象的键。

我尝试过类型交叉(&)、+.concat()

function makeKey<NS extends string, N extends string>(namespace: NS, name: N) {
    return namespace + '/' + name; // <- want this to be `NS + / + N` = `NS/N`
}
// I want this to return a string literal rather than a generic string

const objKey = makeKey('admin', 'home')
// I want typeof objKey to be a string literal: `"admin/home"`, not a generic `string`

typeof objKey 是一个通用的 字符串,但我想要它成为一个 字符串字面量 "admin/home"


在 TypeScript 中,字符串文字是单独的类型吗? - juanpa.arrivillaga
它是字符串类型的子集,与字符串枚举大致相同。 - Dudeonyx
1
目前没有方法可做到这一点。 - Titian Cernicova-Dragomir
2
答案不幸地是否定的。有几个建议可能会给您这个功能([这个] (https://github.com/Microsoft/TypeScript/issues/12754)或[这个](https://github.com/Microsoft/TypeScript/issues/6579)),但我认为这些建议并未得到考虑。 - jcalz
@GetOffMyLawn 模板字面量和字符串字面量是不同的东西,字符串字面量是 TypeScript 类型。 - Dudeonyx
3个回答

47

TS4.1+的答案:

您现在可以使用模板文字类型来实现此操作:

function makeKey<NS extends string, N extends string>(namespace: NS, name: N) {
    return namespace + '/' + name as `${NS}/${N}`
}

const objKey = makeKey('admin', 'home');
// const objKey: "admin/home"

Playground链接


TS4.1版本之前的回答:

不幸的是,答案是。在GitHub上有几个功能建议已经被提交了,如果实现了这些功能(microsoft/TypeScript#12754 用于增加映射类型中的键或者microsoft/TypeScript#6579 通过正则表达式操作字符串类型),这可能会给您带来这样的功能,但我认为它们并没有被积极地开发。 我在 路线图中也没有看到任何相关的内容。如果您真的想看到这个功能实现,您可以去其中一个GitHub问题页面并给出一个“👍”或者描述您的用例,如果它特别引人注目的话。但是我不会抱太大希望了。很抱歉!


谢谢@jcalz!我已经在其中一个线程上留下了我的用例评论。 - mesqueeb
我不知道这是个事情。非常酷,谢谢。 - Jan Paepke

9

一旦模板字符串类型被发布(似乎在 TypeScript 4.1 中),这将变得可能:

function makeKey<NS extends string, N extends string>(namespace: NS, name: N) {
    return (namespace + '/' + name) as `${NS}/${N}`;
}

const objKey = makeKey('admin', 'home') // objKey is of type 'admin/home'

实验场


模板字符串类型是模板字符串表达式的类型空间等效物。 与模板字符串表达式类似,模板字符串类型用反引号括起来,并可以包含占位符,形式为${T},其中T是可分配给stringnumberbooleanbigint的类型。 模板字符串类型提供了连接文本字符串、将非字符串原始类型字面量转换为字符串表示形式以及更改字符串字面量的大写或小写格式的能力。 此外,通过类型推断,模板字符串类型提供了一种简单的字符串模式匹配和分解形式。

一些例子:

type EventName<T extends string> = `${T}Changed`;
type Concat<S1 extends string, S2 extends string> = `${S1}${S2}`;
type T0 = EventName<'foo'>;  // 'fooChanged'
type T1 = EventName<'foo' | 'bar' | 'baz'>;  // 'fooChanged' | 'barChanged' | 'bazChanged'
type T2 = Concat<'Hello', 'World'>;  // 'HelloWorld'
type T3 = `${'top' | 'bottom'}-${'left' | 'right'}`;  // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'

更多细节和示例在此处查看


-5

对我来说有效,使用typescript 3.7.2,使用模板字面量连接和as关键字指定函数的输出类型。

const addSuffixToMyStringLiteral =
    (m: MyStringLiteral, suffix: string) => `${m}${suffix}` as MyStringLiteral;

我不知道这是否是typescript的一个新功能。


响应类型为MyStringLiteral。OP期望例如literalexamplesuffix。 - MistyK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接