You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将TypeScript模板字面量类型转换为ArkType定义?

在ArkType中复现TypeScript模板字面量类型

我正尝试将一些TypeScript类型定义转换为ArkType语法,但遇到了阻碍。具体来说,我想要在ArkType中复现TypeScript的模板字面量类型(例如application/${keyof typeof application}),但不确定所用方法是否正确,也不清楚ArkType是否支持这类类型组合。

以下是我在TypeScript中可以优雅实现的代码:

const text = {
  html: ['html'],
  markdown: ['md'],
  xml: ['xml'],
  plain: ['txt', 'text', 'sh'],
  csv: ['csv'],
  css: ['css'],
  javascript: ['js'],
};

const video = {
  wmv: ['wmv'],
  mp4: ['mp4'],
  mpeg: ['mpeg'],
  matroska: ['mkv'],
};

const audio = {
  mp4: ['mp4'],
  mp3: ['mp3'],
  mpeg: ['mpeg'],
};

const image = {
  png: ['png'],
  jpeg: ['jpg', 'jpeg'],
  avif: ['avif'],
  AV1: ['avi'],
  webp: ['webp'],
};

const application = {
  json: ['json'],
  yaml: ['yaml', 'yml'],
};

export type ApplicationType = `application/${keyof typeof application}`;
export type ImageType = `image/${keyof typeof image}`;
export type VideoType = `video/${keyof typeof video}`;
export type AudioType = `audio/${keyof typeof audio}`;
export type TextType = `text/${keyof typeof text}`;
export type MimeType = ApplicationType | ImageType | VideoType | AudioType | TextType;

然而,我似乎无法将这种方法转换成ArkType可解析的语法。

我曾尝试过几种MediaType的变体方法,但都未成功:

export const { MimeType } = type.module({
  // Subtype unions for each MediaType
  ApplicationSub: "'json' | 'yaml'",
  ImageSub: "'png' | 'jpeg' | 'avif' | 'AV1' | 'webp'",
  VideoSub: "'wmv' | 'mp4' | 'mpeg' | 'matroska'",
  AudioSub: "'mp4' | 'mp3' | 'mpeg'",
  TextSub: "'html' | 'markdown' | 'xml' | 'plain' | 'csv' | 'css' | 'javascript'",

  // MediaTypes with their extensions
  Application: "`application/${ApplicationSub}`", // <-- Type "`application/${ApplicationSub}`" is not assignable to type "'`application/${ApplicationSub}`' is unresolvable".
  Image: "'image/'ImageSub", // <-- Type "'image/'ImageSub" is not assignable to type "'I' is not allowed here".ts(2322)

  Video: "'video/'VideoSub", // <--Type "'video/'VideoSub" is not assignable to type "'V' is not allowed here".
  Audio: "audio/${AudioSub}", // <-- Type "audio/${AudioSub}" is not assignable to type "'audio/${AudioSub}' is unresolvable".
  Text: "text/${TextSub}",

  // Final union type
  MimeType: "Application | Image | Video | Audio | Text"
});

能否有人指点我在ArkType中表达字符串模板类型的正确方向?或者这根本无法实现?

谢谢!


解决方案

ArkType支持实现类似TypeScript模板字面量的字符串联合类型,但语法规则不同,以下是两种可行的实现方式:

方法1:使用template关键字(推荐)

ArkType提供了template语法,可以将固定前缀与子类型联合拼接成目标字符串联合,写法如下:

import { type } from 'arktype'

export const { MimeType } = type.module({
  // 定义子类型联合
  ApplicationSub: "'json' | 'yaml'",
  ImageSub: "'png' | 'jpeg' | 'avif' | 'AV1' | 'webp'",
  VideoSub: "'wmv' | 'mp4' | 'mpeg' | 'matroska'",
  AudioSub: "'mp4' | 'mp3' | 'mpeg'",
  TextSub: "'html' | 'markdown' | 'xml' | 'plain' | 'csv' | 'css' | 'javascript'",

  // 通过template生成带前缀的字符串联合
  Application: "template('application/', ApplicationSub)",
  Image: "template('image/', ImageSub)",
  Video: "template('video/', VideoSub)",
  Audio: "template('audio/', AudioSub)",
  Text: "template('text/', TextSub)",

  // 最终的MimeType联合类型
  MimeType: "Application | Image | Video | Audio | Text"
})

方法2:直接拼接字符串联合

如果追求直观性,也可以手动将前缀与每个子类型拼接,直接定义完整的字符串联合:

import { type } from 'arktype'

export const { MimeType } = type.module({
  Application: "'application/json' | 'application/yaml'",
  Image: "'image/png' | 'image/jpeg' | 'image/avif' | 'image/AV1' | 'image/webp'",
  Video: "'video/wmv' | 'video/mp4' | 'video/mpeg' | 'video/matroska'",
  Audio: "'audio/mp4' | 'audio/mp3' | 'audio/mpeg'",
  Text: "'text/html' | 'text/markdown' | 'text/xml' | 'text/plain' | 'text/csv' | 'text/css' | 'text/javascript'",

  MimeType: "Application | Image | Video | Audio | Text"
})

两种方式都会生成与TypeScript中MimeType完全一致的类型约束,合法值如'application/json'、'image/png'会被允许,不符合格式的字符串会被拦截。

内容的提问来源于stack exchange,提问作者Wayne Griffiths

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:54:50