如何将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
相关产品推荐
相关产品推荐

