TypeScript 复杂的泛型方法

LppEdd

我目前有这个方法

create<T extends ElementType | string>(type: T): Element<T>;

它使用

export type ElementType = 'ExtensionElements' | 'Documentation';

export type Element<T> =
  T extends 'ExtensionElements' ? ExtensionElements :
    T extends 'Documentation' ? Documentation :
      GenericElement;

此方法在 a 中.d.ts,它保证结果始终是类型化的,因​​此

const e1 = obj.create('ExtensionElements');
      ^^ type is ExtensionElements

const e2 = obj.create('Documentation');
      ^^ type is Documentation

const e3 = obj.create('Other');
      ^^ type is GenericElement

现在,我想让这个方法的用户扩展可能的类型选择,例如

type CustomElementType = 'Other' | ElementType;

type CustomElement<T> =
  T extends 'Other' ? CustomOtherElement : Element<T>;

const e4 = obj.create<CustomElementType, CustomElement>('Other');
      ^^ type is CustomOtherElement

然而,这似乎不能正常工作,因为我总是收到所有类型的联合,而且我不能使用任意字符串。

你对我如何实现这个有任何其他想法吗?

提香·切尔尼科娃-德拉戈米尔

您可以使用接口从字符串类型映射到真实类型。由于接口是开放式客户端,因此可以使用模块扩充来添加额外的选项:

// create.ts
export declare let obj: {   
    create<T extends ElementType | string>(type: T): Element<T>;
}
type ExtensionElements = { e: string }
type Documentation = { d: string }
type GenericElement = { g: string }

export type ElementType = 'ExtensionElements' | 'Documentation';
export interface ElementMap {
    'ExtensionElements': ExtensionElements;
    'Documentation': Documentation;
}
export type Element<T extends string> = ElementMap extends Record<T, infer E> ? E :
    GenericElement;

const e1 = obj.create('ExtensionElements'); // ExtensionElements
const e2 = obj.create('Documentation'); // Documentation
const e3 = obj.create('Else'); //GenericElement

// create-usage.ts
import { obj } from './create'
type CustomOtherElement = { x: string }

declare module './create' {
    export interface ElementMap {
        'Other': CustomOtherElement
    }
}
const e4 = obj.create('Other'); //  CustomOtherElement

如果要进行范围扩展,则需要一个额外的函数来更改用于将字符串映射到对象类型的接口。这个方法可以只返回当前对象作为预期结果(因为类型在运行时无关紧要,没有什么需要不同)

// create.ts
interface Creator<TMap = ElementMap>{
    create<T extends keyof TMap | string>(type: T): Element<TMap, T>;
    extend<TMapExt extends TMap>(): Creator<TMapExt>
}
export declare let obj: Creator
type ExtensionElements = { e: string }
type Documentation = { d: string }
type GenericElement = { g: string }

import { obj, ElementMap } from './create'
type CustomOtherElement = { x: string }

export type ElementType = 'ExtensionElements' | 'Documentation';
export interface ElementMap {
    'ExtensionElements': ExtensionElements;
    'Documentation': Documentation;
}
export type Element<TMap, T extends PropertyKey> = TMap extends Record<T, infer E> ? E : GenericElement;

const e1 = obj.create('ExtensionElements'); // ExtensionElements
const e2 = obj.create('Documentation'); // Documentation
const e3 = obj.create('Else'); //GenericElement


// create-usage.ts
export interface CustomElementMap extends ElementMap {
    'Other': CustomOtherElement
}
const customObj = obj.extend<CustomElementMap>()
const e4 = customObj.create('Other'); //  CustomOtherElement

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Typescript推断泛型中的泛型

来自分类Dev

泛型类型推断的 Typescript 泛型

来自分类Dev

TypeScript-如何从方法的参数推断类的泛型?

来自分类Dev

在 TypeScript 泛型方法中将变量转换为 T?

来自分类Dev

具有类型依赖参数的 TypeScript 泛型方法

来自分类Dev

使用 TypeScript checkJs 在 JSDoc 中扩展泛型类型的方法?

来自分类Dev

TypeScript,泛型和instanceof

来自分类Dev

Typescript中的泛型转换

来自分类Dev

TypeScript泛型传递枚举

来自分类Dev

TypeScript泛型创建实例

来自分类Dev

TypeScript,泛型和instanceof

来自分类Dev

Typescript:泛型,使用泛型扩展类型

来自分类Dev

强制泛型在TypeScript中实现属性(约束泛型)

来自分类Dev

TypeScript泛型:参数类型推断

来自分类Dev

Typescript中的泛型是什么?

来自分类Dev

Typescript泛型扩展类和接口

来自分类Dev

在TypeScript中使用泛型扩展接口

来自分类Dev

Typescript:从泛型类型获取文字值

来自分类Dev

Typescript中的默认泛型类型派生

来自分类Dev

TypeScript中泛型的深度条件类型

来自分类Dev

通过泛型缩小TypeScript索引类型

来自分类Dev

嵌套TypeScript函数中的泛型

来自分类Dev

TypeScript泛型-回调函数推论

来自分类Dev

Typescript中泛型格式的歧义

来自分类Dev

泛型类型的TypeScript函数重载

来自分类Dev

无法使TypeScript泛型链起作用

来自分类Dev

从静态属性推断Typescript泛型

来自分类Dev

在 TypeScript 的嵌套泛型中创建实例

来自分类Dev

Typescript 泛型和 rxjs 映射