npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@xinmier/lei-xing--tong-yong

v1.6.0

Published

辛米尔 TypeScript 语言的通用类型集。

Downloads

7

Readme

辛米尔 TypeScript 语言的通用类型集

npm 包

npm 包之名称

@xinmier/lei-xing--tong-yong

npm 包之主页

https://www.npmjs.com/package/@xinmier/lei-xing--tong-yong

概述

有些 TypeScript 之类型异常通用,却未必对应到特定的 TypeScript(JavaScript)工具或组件代码上。故搜集于此。

注:倘若某通用之类型专用于或依附于某特定的某工具组件,那么那些通用类型应存在与那些工具或组件存放在一起。

本类型集全部在名为 @xinmier/lei-xing--tong-yong 的【模块(module)】下。

用法(面向网页开发人员)

安装

在命令行环境中,cd 进入你的网页开发项目的文件夹,并执行以下命令:

npm  i  @xinmier/lei-xing--tong-yong

在代码中使用本组件(仅涉及导入)

因本类型集中之一切(公开)类型均定义在 @xinmier/lei-xing--tong-yong 模块下,故引用它们的办法是统一的。参见下例:

import type {
    T_Xme_CssClassNamesConfigObject,
    T_Xme_NetworkHostConfig_Unresolved,
    T_Xme_NetworkHostConfig_Resolved,
    T_XmeTool_GetUiTextMapperFromObject_AllOptional,
} from '@xinmier/lei-xing--tong-yong'

内容详表

【界面元素的情态】

设计初衷

界面中,常常出现所谓“情态”。外国话是 mood ,意为心情、口吻、氛围。

常见的做法是,用绿色代表积极的含义,红色代表错误或危险,黄色代表警示,等等。但不论设计师采用那种具体的色彩,也不论程序员选用那种具体的配色方案,情态往往是相对固定不变的。

所以我们设计了如下枚举类型,以便在诸如按钮、菜单项、情态图标等视觉元素上运用。

现实中的例子如 Element-Plus 中的:

  • el-button--info
  • el-button--success
  • el-button--warning
  • el-button--danger

等。

可惜 Element-Plus 措辞时,并未严格采用表达情态的词语,而是混用了 infosuccess 这样的词语。

该套类型定义之全文

界面元素情态的完整定义非常简单,全文如下:

export declare type T_Xme_UiMood_Id = (
    | 'plain'      // 平实。
    | 'positive'   // 积极。一般对应 Successful 、 Succeed 、 OK 等。
    | 'negative'   // 消极。一般对应 Failure 、 Error 、Exception 等。
    | 'noteworthy' // 值得警醒。一般对应 Warning 。
);

export declare type T_Xme_UiMood_IdLong = `mood-${T_Xme_UiMood_Id}`;

export declare type T_Xme_UiMood_CssClassName = `xme-ui-mood--${T_Xme_UiMood_Id}`;


export const XME_UI_MOOD__SHORT_ID__ALL_ALLOWED_VALUES: T_Xme_UiMood_Id[] = [
    'plain',
    'positive',
    'negative',
    'noteworthy',
]

export const XME_UI_MOOD__LONG_ID__ALL_ALLOWED_VALUES: T_Xme_UiMood_IdLong[] = [
    'mood-plain',
    'mood-positive',
    'mood-negative',
    'mood-noteworthy',
]

export const XME_UI_MOOD__CSS_CLASS_NAME__ALL_ALLOWED_VALUES: T_Xme_UiMood_CssClassName[] = [
    'xme-ui-mood--plain',
    'xme-ui-mood--positive',
    'xme-ui-mood--negative',
    'xme-ui-mood--noteworthy',
]

折行大体可控的【界面文本配置】

设计初衷

通常,界面文本即是普通的 string 。例:

const someUiText: string = '美帝国主义必亡!'

但有时我们会遇到需要控制文本折行的情形。例如,页面顶部的公司全称往往很长,当浏览器窗口变窄时,公司全称之折行不能太随意,须加以控制。例如“铁拐李汉钟离蓝采和何仙姑海上航运股份有限公司”一语,在须折行时,应优先在“股份”二字之前折行。又,“铁拐李”、“汉钟离”、“蓝采和”与“何仙姑”四个人名应尽量不折行,除非浏览器排版空间窄小到一行连区区三个汉字都容不下那样的情形。

为满足这类文字排版要求,不妨将较长的文本(例如上述公司全称)分割成若干片段。每个片段由一个行内元素(一般是 <span>)容纳。该行内元素之样式之 displayinline-block 。 由此,当浏览器足够宽大、文本排版空间富足时,文本自然聚成单行,即不折行;而当文本排版空间局促时,文本会以上述行内元素为单位折行。 落实到类型定义,则无外乎是一个文本列表,即 Array<string> 。例:

const someUiText2: T_Xme_UiTextConfig = [
    '台湾省', '是中华人民共和国', '不可分割的一部分!'
]

又,偶尔,我们须令界面文本包含特殊字符,且不得不以 HTML Entity 之方法表达它。 于此种情形,应允许界面文本携带额外的标记来记载文本自身是否包含 HTML Entity 。

综上,界面文本可以是两大类:一,单一【片段】;二,多个【片段】组成的【列表】。

其中,单一【片段】又有两种形态:甲,平实的【文本】,即 string ;乙,略复杂的【结构】,以便包含 HTML Entity 。

汇总可得,完整的数据种类划分如下:

  1. 单一【片段】。

    1. 平实的【文本】,即 string
    2. 略复杂的【结构】,以便包含 HTML Entity 。
  2. 多个【片段】组成的【列表】。

又,本 npm 包中,仅涉及与上述要求相适应的类型定义(采用 TypeScript 语言),而不涉及适应上述要求的具体实现。 辛米尔网页技术团队另行设计了一个独立的 npm 包,名为《界面简短措辞(@xinmier/ui--words)》,即是适应上述要求的 Vuejs 3 实现。

该套类型定义之全文

界面文本相关的类型定义全文如下:

export declare type T_Xme_UiTextConfig_SingleTextSnippet_PlainText = string;

export declare type T_Xme_UiTextConfig_SingleTextSnippet_AllowHtmlEntity = {
    isHTML: boolean;
    htmlText: string;
};

export declare type T_Xme_UiTextConfigStatic = (
    | T_Xme_UiTextConfig_SingleTextSnippet_PlainText
    | T_Xme_UiTextConfig_SingleTextSnippet_AllowHtmlEntity
    | Array<T_Xme_UiTextConfig_SingleTextSnippet_PlainText | T_Xme_UiTextConfig_SingleTextSnippet_AllowHtmlEntity>
);

export declare type T_Xme_UiTextConfigGenerator = (...args: any[]) => T_Xme_UiTextConfigStatic;

export declare type T_Xme_UiTextConfig = T_Xme_UiTextConfigStatic | T_Xme_UiTextConfigGenerator;

不妨参阅源代码《UiText.ts》。

示例集

示例 1:

import type {
    T_Xme_UiTextConfig,
} from '@xinmier/lei-xing--tong-yong'

const greetingText: T_Xme_UiTextConfig = [
    '我爱你',
    '中国',
]

若设计一个组件以处理上述片段集,则该组件最终应产生以下 HTML 片段:

<span ...>我爱你</span><span ...>中国</span>

示例 2:

import type {
    T_Xme_UiTextConfig,
} from '@xinmier/lei-xing--tong-yong'

const appFullTitle: T_Xme_UiTextConfig = [
    '辛米尔视觉科技',
    '(上海)有限公司',
    {
        isHTML: true,
        htmlText: 'EventCAM&reg;', // 这里有 HTML Entity: &reg; 。
    },
]

若设计一个组件以处理上述片段集,则该组件最终应产生以下 HTML 片段:

<span ...>辛米尔视觉科技</span><span ...>(上海)有限公司</span><span ...>EventCAM&reg;</span>
为何该组类型设计脱离相关组件而独立存在?

既然界面文本落实到应用软件之代码时,须依赖于具体的组件,那为何要令这些类型定义脱离组件而存在于本类型集中呢? 原因是这些界面文本类型太过常用,特别是常常被其他通用类型引用。倘若将这些界面文本相关的类型绑定在某组件代码中,则定义其余的通用类型颇为不便。

【层叠样式表取值】

【层叠样式表】规范中的【长度值】。

参见《https://developer.mozilla.org/en-US/docs/Web/CSS/length》。

export declare type T_Xme_CssValue_Length = `${number}${ 'px' | 'em' | 'rem' | 'vw' | 'vh' | 'ex' | 'ic' | 'ch' | 'lh' | 'rlh' }`;

不妨参阅源代码《Css.ts》。

【层叠样式表】规范中的【时长值】

参见《https://developer.mozilla.org/en-US/docs/Web/CSS/time》。

export declare type T_Xme_CssValue_Time   = `${number}${ 's' | 'ms' }`;

不妨参阅源代码《Css.ts》。

【样式类名之配置】

设计初衷

【样式类名】,即 CSS Class Names 。

不论是 Vuejs 的组件还是 Reactjs 的组件,都接受可配置的样式类名集,且形式灵活多变。 一般的,可以接受以下三类:

  1. 字符串,
  2. 字符串列表,
  3. 一个键值对。其中键视为样式类名,值视为布尔值。凡某键之值等效为 true ,则该键代表的样式类名被采用;反之。

只是,Vuejs 中与上述样式类名配置相关的类型定义不够“精彩”,于是我自行设计了更实用的类型定义。如下文。

该套类型定义之全文
export type T_Xme_CssClassNamesConfigObject<
    _T_RequiredCssClassNames extends string = never,
    _T_OptionalCssClassNames extends string = string
> = {
    [cssClassName in _T_RequiredCssClassNames]:  boolean;
} & {
    [cssClassName in _T_OptionalCssClassNames]?: boolean;
};

export type T_Xme_CssClassNameList<
    _T_RequiredCssClassNames extends string = never,
    _T_OptionalCssClassNames extends string = string
> = Array<_T_RequiredCssClassNames | _T_OptionalCssClassNames>;

export type T_Xme_CssClassNamesConfig<
    _T_RequiredCssClassNames extends string = never,
    _T_OptionalCssClassNames extends string = string
> = (
    | _T_RequiredCssClassNames
    | _T_OptionalCssClassNames
    | T_Xme_CssClassNamesConfigObject<_T_RequiredCssClassNames, _T_OptionalCssClassNames>
    | T_Xme_CssClassNameList         <_T_RequiredCssClassNames, _T_OptionalCssClassNames>
);

不妨参阅源代码《Css.ts》。

示例集

示例 1:

import { computed } from 'vue'

import type {
    T_Xme_UiMood,
} from '@xinmier/lei-xing--tong-yong'

const cssClassNamesOfRootElement = computed<T_Xme_CssClassNamesConfigObject<
    'ui-root',
    'is-wide' | 'is-narrow' | T_Xme_UiMood
>>(() => {
    return {
        'ui-root': true,
        'is-wide': false,
        'is-narrow': !0,
        'xme-ui-mood--positive': true,
    }
})

示例 2:

import { computed } from 'vue'

import type {
    T_Xme_UiMood,
} from '@xinmier/lei-xing--tong-yong'

const cssClassNames = computed<T_Xme_CssClassNamesConfigObject<
    'ui-root',
    'is-wide' | 'is-narrow' | T_Xme_UiMood
>>(() => [ 'ui-root', 'is-narrow', 'xme-ui-mood--positive' ])

【网络主机】

设计初衷

客户端程序与服务端程序通讯,最基本的配置就是网络主机。网络主机涵盖【协议】、【主机名】或【主机IP地址】、【端口号】几个部分。

这些主机配置可能在多处出现。典型的,会出现在环境配置文件中。又,为简化配置,应允许配置设计者仅填写部分内容,其余采取默认值。 是故,设计了一组类型定义,以为辅助。

该套类型定义

该套类型最主要的部分有两个:

  1. 用以设计主机配置的形式。该形式中,若干属性可省略。 称为 T_Xme_NetworkHostConfig_Unresolved

    凡符合该形式之数据,交由特定的工具函数处理,会得到完整的形式。

  2. 用以表达工具函数最终求得的完整形式。该形式中,字段齐备,无有省略。 称为 T_Xme_NetworkHostConfig_Resolved

注意!本工具仅提供网络主机之类型定义,并不提供上述工具函数。

该类型定义之全文
export declare type T_Xme_NetworkProtocolName1 = (
    | 'ftp:'
    | 'http:'
    | 'https:'
    | 'ws:'
    | 'wss:'
    | 'rstp:'
    | 'rstps:'
    | 'rstpu:'
);

export declare type T_Xme_IpV4     = `${number}.${number}.${number}.${number}`;
export declare type T_Xme_IpV4Mask = T_Xme_IpV4;
export declare type T_Xme_IpV6     = string;



export declare type T_Xme_HttpMethod_UpperCase = 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH' | 'HEAD' | 'CONNECT' | 'OPTIONS' | 'TRACE';
export declare type T_Xme_HttpMethod_LowerCase = Lowercase<T_Xme_HttpMethod_UpperCase>;
export declare type T_Xme_HttpMethod = T_Xme_HttpMethod_UpperCase | T_Xme_HttpMethod_LowerCase;



export declare interface T_Xme_NetworkHostConfig_Unresolved<
    _T_Protocol extends `${string}:` = T_Xme_NetworkProtocolName1,
    _T_NameOrIp extends    string    = string,
    _T_Port     extends    number    = number
> {
    descriptionOfTheServer?:  string;
    descriptionOfTheService?: string;

    protocol?:                _T_Protocol;
    nameOrIp:                 _T_NameOrIp;
    port?:                    _T_Port;
}

export declare interface T_Xme_NetworkHostConfig_Resolved<
    _T_Protocol extends `${string}:` = T_Xme_NetworkProtocolName1,
    _T_NameOrIp extends    string    = string,
    _T_Port     extends    number    = number
> {
    protocol: _T_Protocol;
    nameOrIp: _T_NameOrIp;
    port:     _T_Port;
}

export declare interface T_Xme_NetworkHost<
    _T_Protocol extends `${string}:` = T_Xme_NetworkProtocolName1,
    _T_NameOrIp extends    string    = string,
    _T_Port     extends    number    = number
> {
    descriptionOfTheServer:  string;
    descriptionOfTheService: string;

    fullHost:
        | `${_T_Protocol}//${T_Xme_NetworkHostConfig_Resolved<_T_Protocol, _T_NameOrIp, _T_Port>['nameOrIp']}`
        | `${_T_Protocol}//${T_Xme_NetworkHostConfig_Resolved<_T_Protocol, _T_NameOrIp, _T_Port>['nameOrIp']}:${T_Xme_NetworkHostConfig_Resolved<_T_Protocol, _T_NameOrIp, _T_Port>['port']}`
    ;

    config: T_Xme_NetworkHostConfig_Resolved<_T_Protocol, _T_NameOrIp, _T_Port>;
}

export declare type T_Xme_NetworkHost_FullText<
    _T_Protocol extends `${string}:` = T_Xme_NetworkProtocolName1,
    _T_NameOrIp extends    string    = string,
    _T_Port     extends    number    = number
> = T_Xme_NetworkHost<_T_Protocol, _T_NameOrIp, _T_Port>['fullHost'];
随附工具
export function xmeNetworkHost_EvaluateFullHost<_T_Protocol extends T_Xme_NetworkProtocolName1 = T_Xme_NetworkProtocolName1>(
    options: {
        hostConfig?: null | T_Xme_NetworkHostConfig_Unresolved<_T_Protocol>;
        hostDefaultconfig:  T_Xme_NetworkHostConfig_Unresolved<_T_Protocol>;
        descriptionOfTheServer?:  string;
        descriptionOfTheService?: string;
    }
): T_Xme_NetworkHost<_T_Protocol>;

不妨参阅源代码《Network.ts》。

示例集

示例:

import type {
    T_Xme_NetworkHostConfig_Unresolved,
    T_Xme_NetworkHostConfig_Resolved,
} from '@xinmier/lei-xing--tong-yong'

const dataService_HttpsHost1: T_Xme_NetworkHostConfig_Unresolved<'https:'> = {
    protocol: 'http:', // 这一行将报错。因为类型定义要求 protocol 只能是 'https:' 。
    nameOfIp: '192.168.5.15',
    port: 2013,
}

const dataService_WebSocketHost1: T_Xme_NetworkHostConfig_Unresolved<
    'ws:', string, 1234 | 2345
> = {
    protocol: 'ws:',
    nameOfIp: '192.168.5.15',
    port: 2013, // 这一行将报错。因为类型定义要求 port 只能为 1234 或 2345 。
}

const myAppHost1: T_Xme_NetworkHostConfig_Unresolved<
    'myapp:'
> = {
    protocol: 'myapp:',
    nameOfIp: 'localhost',
}
该套类型设计为何脱离相关组件而独立存在?

既然要求得网络主机之完整定义,须依赖于具体的组件,那为何要令这些类型定义脱离组件而存在于本类型集中呢? 原因是网络主机类型太过常用,特别是常常被其他通用类型引用。倘若将这些类型绑定在某组件代码中,则定义其余的通用类型颇为不便。

【XHR 网络请求失败】

设计初衷

某些 XHR 请求失败,是因为 401 (无权限)或 404(未找到对应资源)。此时,不论该失败之请求发生在应用程序的那个角落,程序员都可能采用固定的代码做统一处理。倘若程序员果然打算采取统一措施处理这类特别的失败,则应在这些失败发生时做好专门标记。这些标记不妨称所谓“信号(Signal)”。该套类型定义即是为了辅助程序员设计和使用这些信号的。

又,既然允许为特定种类的失败做标记,那不妨也允许程序员临时订制其他的失败标记。故而,本组类型定义包含两大类:

  1. HTTP 标准的失败信号,
  2. 非标准的失败信号。
该套类型定义之全文
export declare type T_Xme_XhrSpecialCodeNumber = 401 | 403 | 404 | 500 | 502 | 503 | 504;
export declare type T_Xme_XhrSpecialCodeText   = `${T_Xme_XhrSpecialCodeNumber}`;

/**
 * 某些 XHR 请求失败,是因为 `401` (无权限)或 `404`(未找到对应资源)。
 * 此时,不论该失败之请求发生在应用程序的那个角落,
 * 程序员都可能采用固定的代码做统一处理。
 * 倘若程序员果然打算采取统一措施处理这类特别的失败,
 * 则应在这些失败发生时做好专门标记。
 * 这些标记不妨称所谓“信号(Signal)”。
 * 该组类型定义即是为了辅助程序员设计和使用这些信号的。
 */
export declare type T_Xme_XhrFailureSpecialSignals_HttpStandard = {
    [_T in T_Xme_XhrSpecialCodeText as `isHttp${_T}`]: boolean;
};

export declare interface T_Xme_XhrFailureSpecialSignals_NonStandard {
    // isAuthTokenTimeout: boolean;
}

export declare type T_Xme_XhrFailureSpecialSignals = T_Xme_XhrFailureSpecialSignals_HttpStandard & T_Xme_XhrFailureSpecialSignals_NonStandard;

export declare interface T_Xme_XhrRejectionReason<_T_ResponseData = any, _T_RequestPayload = any> {
    response:                 null | AxiosResponse<_T_ResponseData, _T_RequestPayload>;
    axiosError:               null | AxiosError   <_T_ResponseData, _T_RequestPayload>;
    errorMessageForEndUser:   Error;
    specialSignalsOfTheError: T_Xme_XhrFailureSpecialSignals;
}

不妨参阅源代码《DataServicesViaHttp.ts》。

示例

示例:

import type {
    T_Xme_XhrFailureSpecialSignals,
} from '@xinmier/lei-xing--tong-yong'

const specialSignalsOfTheFailure: T_Xme_XhrFailureSpecialSignals = {
    isHttp401:          false,
    isHttp403:          false,
    isHttp404:          false,
    isHttp500:          false,
    isHttp502:          false,
    isHttp503:          false,
    isHttp504:          false,
    isAuthTokenTimeout: false,
}

XHR 网络请求响应:响应之内容为标准列表

设计初衷

实践中,凭 XHR 请求取得一个数据列表乃是司空见惯的事情。但各个项目的服务端程序,乃至同一个项目中服务端程序的不同接口,给出的列表格式可能迥异。为在客户端形成统一固定的格式,遂设计了该类型定义。

须知,本工具集仅给出类型定义,无任何算法逻辑。故将特定的服务端列表格式转换为下方统一的客户端列表格式的工具函数须单独编写。不难想象,各个项目,乃至同一项目的各个接口,均可能要求编写独特的工具函数,用以转换格式,难以通用。

该类型定义之全文
export declare interface T_Xme_XhrResponse_StandardPaginatedList<_T_RawRecord> {
    list: _T_RawRecord[];
    entriesCountPerPage: number;
    entriesTotalCount: number;
}

不妨参阅源代码《DataServicesViaHttp.ts》。

类型定义之辅助工具:凭某【键值对】得出其相应的【界面文本字典】

设计初衷

实践中,客户端常常遇到这样的编程任务,须将某字典以文本呈现在界面某处。例如,一个表格的表头,其中各项对应表格数据的各字段。这些字段名和表格表头中的文本不是一回事。特别多,表头中的文本可能按需翻译成不同语种的文本。再如,若要为某表格制作【表格条目过滤器】表单,则表格数据中的字段凡应出现在过滤器表单中的,也应各有对应的【界面文本】。

例:

const someList = [
    { name: '孙悟空', age: 3000, weapon: '如意金箍棒' },
    { name: '猪八戒', age: 4000, weapon: '上宝沁金耙' },
]

上例中,nameageweapon 都是字段名,而它们对应的界面文本如果是汉语,则可能是“姓名”、“年龄”和“宝器”或“武器”。

此类对应关系看似简单,却往往用在多处。尤其那些以表格为主体的页面,同一个字段,其对应的【界面文本】往往须在过滤器、表头、数据详情表单等多处出现。 为统一解决从字段名到【界面文本】的映射关系之定义之问题,应设计一工具来高效工具专攻于此。

又,上述对应关系显然适合采用【键值对】来记载,故不妨称【界面文本映射字典】,或简称【界面文本字典】。故,该套类型定义之辅助工具不妨称为【界面文本字典】之类型设计工具或生成工具。 顾名思义,该工具仅用于设计映射字典之类型,并不产出真正的映射字典。

倘若无此类辅助工具,则常见的映射表的类型定义大体如下:

type T_UiTextMapper = Record<string, string>;

但以上的类型定义过于宽泛,不能“享受” TypeScript 语言强大的类型检查功能。遂不妨做如下假设性的改进:

type T_UiTextMapperOfTable1 = Record<
    'name' | 'age' | 'weapon',
    string
>;

上例已经较为实用了,它限定了映射字典的【键值对】的【键】仅允许采取 nameageweapon 三者,别无其他。 但上述假想的做法仍不完美。因为【键值对】的【键】是人为(或者说手工)书写的,不够自动化。 实践中,【键值对】的【键】往往在其他类型中已经定义过了,没必要在设计【界面文本字典】的类型时,再人为书写一遍。 仍以表格为例,程序员大概率会先定义好该表格每条记录的类型,假设如下:

type T_ChineseHerosRecord = {
    name: string;
    age: number;
    weapon: string;
};

如上,nameageweapon 已经出现了。 当为这样的数据记录设计【界面文本字典】的类型时,最理想的做法是根据上述给定、现成的 T_ChineseHerosRecord 自动构建出【界面文本字典】的类型。

小结

我们的目标很明确,一旦有给定的其他对象的类型定义(甲),我们要设计一个工具,可从甲产生一个新的类型定义(乙),使得乙是甲的所有字段的【界面文本】映射项。故而,乙作为整体,可充当服务于甲的【界面文本字典】的类型。

顺便指出,由于在 TypeScript 的世界中,从一个类型得出另一个类型,所用的工具本身也是一个类型。即是说,甲、乙、工具三者都是类型。其中,工具读取(或者说接受)甲,并产生乙。

我设计的该套类型,作为辅助工具则具备上述功能。见下文。

该套类型定义之全文
import type {
    T_Xme_UiTextConfig,
} from './UiText'



// 产生的所谓乙,其每个字段都可省略,即都带有问号(?)。
export declare type T_XmeTool_GetUiTextMapperFromObject_AllOptional<
    _T_InputObject,
    _T_UiText = T_Xme_UiTextConfig
> = _T_InputObject extends Record<string, any>
    ? {
        [sourceText in (string & keyof _T_InputObject)]?: _T_InputObject[sourceText] extends Record<string, any>
            ? T_XmeTool_GetUiTextMapperFromObject_AllOptional<_T_InputObject[sourceText]>
            : _T_UiText
    }
    : Record<never, never>
;



// 产生的所谓乙,其每个字段都不可省略,即都不带有问号(?)。
export declare type T_XmeTool_GetUiTextMapperFromObject_AllRequired<
    _T_InputObject,
    _T_UiText = T_Xme_UiTextConfig
> = _T_InputObject extends Record<string, any>
    ? {
        [sourceText in (string & keyof _T_InputObject)]: _T_InputObject[sourceText] extends Record<string, any>
            ? T_XmeTool_GetUiTextMapperFromObject_AllRequired<_T_InputObject[sourceText]>
            : _T_UiText
    }
    : Record<never, never>
;

类型定义之【爪哇脚本语言通用对象记法】(JSON)

设计初衷

【爪哇脚本语言通用对象记法】,简称 JSON 。其是 JavaScript 对象的子集。例如 JSON 严格要求【键】采用双引号括起来;【键】不可以是 Symbol 。【值】不可以是函数、 undefinedNaNInfinity 等。

故,由此套类型定义。

另,在类型定义层面,无法排除 NaNInfinity

该套类型定义之全文
export declare type T_Xme_Json_AllowedSimpleValue = (
    | number
    | string
    | boolean
    | null
);



export declare type T_Xme_Json_List = Array<T_Xme_Json>;

export declare interface T_Xme_Json_Dict {
    [key: string]: T_Xme_Json;
}

export declare type T_Xme_Json = (
    | T_Xme_Json_AllowedSimpleValue
    | T_Xme_Json_List
    | T_Xme_Json_Dict
);



export declare type T_Xme_Json_AllowedSimpleValue_Loosened = T_Xme_Json_AllowedSimpleValue | undefined;

export declare type T_Xme_Json_List_MemberTypesLoosened = Array<T_Xme_Json_AllowedSimpleValue_Loosened>;

export declare interface T_Xme_Json_Dict_ValueTypesLoosened {
    [key: string]: T_Xme_Json_ValueTypesLoosened;
}

export declare type T_Xme_Json_ValueTypesLoosened = (
    | T_Xme_Json_AllowedSimpleValue_Loosened
    | T_Xme_Json_List_MemberTypesLoosened
    | T_Xme_Json_Dict_ValueTypesLoosened
);

令本套类型集中的诸类型全局可用

全局可用的类型声明,官方说法是所谓“Ambient Declarations”。

理论上,本套类型集中诸类型之命名格外谨慎,故几无可能与第三方类型之命名重叠。但为求格外稳妥,本套类型集故意没有设计成全局可用的。恰如本文《在代码中使用本组件(仅涉及导入)》章节所述, 采用本套类型集中之类型,均须借助 import 语句先引入之。

若为求便利,确需将本套类型集全部改为全局可用之形式,须手工创建一个 .ts 文件,或 .d.ts 文件。并写入以下内容全文。该文件可存放在你的代码库中几乎任何位置,可采取任何名称。例,不妨令该文件名为 @xinmier-tong-yong.ts ,且不妨存放在 <项目根文件夹>/src/global/ 文件夹内。

另, tsconfig.json 须有正确的配置,以确保 TypeScript 语言处理机在处理源代码时,能将上述文件囊括在内。

还需注意,凡【泛型】,即设计了参数的类型,不能简单的采用 type T = 的形式来定义别名,故而不能简单的做到令它们变成全局可用。凡泛型,要么不厌其烦的为其别名设计泛型参数,要么干脆放弃令其提升至 Ambient 之做法。

import type * as XinMiEr from '@xinmier/lei-xing--tong-yong'

declare global {
    /**
     * 凡泛型,要么不厌其烦的为其别名设计泛型参数,要么干脆放弃令其提升至 Ambient 之做法。
     * 另, import as 之形式暂无办法“制作”出 Ambient 类型。
     */

    // ----- Css -----

    // type T_Xme_CssClassNamesConfigObject                       = XinMiEr.T_Xme_CssClassNamesConfigObject;
    // type T_Xme_CssClassNameList                                = XinMiEr.T_Xme_CssClassNameList;
    // type T_Xme_CssClassNamesConfig                             = XinMiEr.T_Xme_CssClassNamesConfig;
    type T_Xme_CssValue_Length                                 = XinMiEr.T_Xme_CssValue_Length;
    type T_Xme_CssValue_Time                                   = XinMiEr.T_Xme_CssValue_Time;



    // ----- DataServicesViaHttp -----

    type T_Xme_XhrSpecialCodeNumber                            = XinMiEr.T_Xme_XhrSpecialCodeNumber;
    type T_Xme_XhrSpecialCodeText                              = XinMiEr.T_Xme_XhrSpecialCodeText;
    type T_Xme_XhrFailureSpecialSignals_HttpStandard           = XinMiEr.T_Xme_XhrFailureSpecialSignals_HttpStandard;
    type T_Xme_XhrFailureSpecialSignals_NonStandard            = XinMiEr.T_Xme_XhrFailureSpecialSignals_NonStandard;
    type T_Xme_XhrFailureSpecialSignals                        = XinMiEr.T_Xme_XhrFailureSpecialSignals;
    // type T_Xme_XhrRejectionReason                              = XinMiEr.T_Xme_XhrRejectionReason;
    // type T_Xme_XhrResponse_StandardPaginatedList<_T_RawRecord> = XinMiEr.T_Xme_XhrResponse_StandardPaginatedList<_T_RawRecord>;



    // ----- Network -----

    type T_Xme_NetworkProtocolName1                            = XinMiEr.T_Xme_NetworkProtocolName1;
    type T_Xme_IpV4                                            = XinMiEr.T_Xme_IpV4;
    type T_Xme_IpV6                                            = XinMiEr.T_Xme_IpV6;
    type T_Xme_HttpMethod_UpperCase                            = XinMiEr.T_Xme_HttpMethod_UpperCase;
    type T_Xme_HttpMethod_LowerCase                            = XinMiEr.T_Xme_HttpMethod_LowerCase;
    type T_Xme_HttpMethod                                      = XinMiEr.T_Xme_HttpMethod;

    // type T_Xme_NetworkHostConfig_Unresolved                    = XinMiEr.T_Xme_NetworkHostConfig_Unresolved;
    // type T_Xme_NetworkHostConfig_Resolved                      = XinMiEr.T_Xme_NetworkHostConfig_Resolved;
    // type T_Xme_NetworkHost                                     = XinMiEr.T_Xme_NetworkHost;
    // type T_Xme_NetworkHost_FullText                            = XinMiEr.T_Xme_NetworkHost_FullText;



    // ----- Tools-GetUiTextMapper -----

    type T_XmeTool_GetUiTextMapperFromObject_AllOptional<
        _T_InputObject,
        _T_UiText = T_Xme_UiTextConfig
    > = XinMiEr.T_XmeTool_GetUiTextMapperFromObject_AllOptional<_T_InputObject, _T_UiText>;

    type T_XmeTool_GetUiTextMapperFromObject_AllRequired<
        _T_InputObject,
        _T_UiText = T_Xme_UiTextConfig
    > = XinMiEr.T_XmeTool_GetUiTextMapperFromObject_AllRequired<_T_InputObject, _T_UiText>;



    // ----- UiMood -----

    type T_Xme_UiMood_Id                                       = XinMiEr.T_Xme_UiMood_Id;
    type T_Xme_UiMood_IdLong                                   = XinMiEr.T_Xme_UiMood_IdLong;
    type T_Xme_UiMood_CssClassName                             = XinMiEr.T_Xme_UiMood_CssClassName;



    // ----- UiText -----

    type T_Xme_UiTextConfig_SingleTextSnippet_PlainText        = XinMiEr.T_Xme_UiTextConfig_SingleTextSnippet_PlainText;
    type T_Xme_UiTextConfig_SingleTextSnippet_AllowHtmlEntity  = XinMiEr.T_Xme_UiTextConfig_SingleTextSnippet_AllowHtmlEntity;
    type T_Xme_UiTextConfigStatic                              = XinMiEr.T_Xme_UiTextConfigStatic;
    type T_Xme_UiTextConfigGenerator                           = XinMiEr.T_Xme_UiTextConfigGenerator;
    type T_Xme_UiTextConfig                                    = XinMiEr.T_Xme_UiTextConfig;



    // ----- JSON -----

    type T_Xme_Json_AllowedSimpleValue                         = XinMiEr.T_Xme_Json_AllowedSimpleValue;
    type T_Xme_Json_List                                       = XinMiEr.T_Xme_Json_List;
    type T_Xme_Json_Dict                                       = XinMiEr.T_Xme_Json_Dict;
    type T_Xme_Json                                            = XinMiEr.T_Xme_Json;

    type T_Xme_Json_AllowedSimpleValue_Loosened                = XinMiEr.T_Xme_Json_AllowedSimpleValue_Loosened;
    type T_Xme_Json_List_MemberTypesLoosened                   = XinMiEr.T_Xme_Json_List_MemberTypesLoosened;
    type T_Xme_Json_Dict_ValueTypesLoosened                    = XinMiEr.T_Xme_Json_Dict_ValueTypesLoosened;
    type T_Xme_Json_ValueTypesLoosened                         = XinMiEr.T_Xme_Json_ValueTypesLoosened;
}

不妨参阅源代码《Json.ts》。