通过TypeScript中的另一个泛型类型保留泛型类型

dx_over_dt

我正在考虑在@testing-library/react和/或中提交类型声明的一个或多个补丁@testing-library/dom目前,对的RenderResultreturn变体的所有查询HTMLElement都使我编写了很多代码,例如

const myDiv = wrapper.getByText('some text') as HTMLDivElement;

最简单的解决方案是使查询通用。

export type GetByText = <T extends HTMLElement = HTMLElement>(/* ... */) => T
export const getByText: GetByText

然后我可以这样做:

const myDiv = wrapper.getByText<HTMLDivElement>('some text');

尽管这在TS Playground中有效,但某些方面@testing-library/react阻止了通用形式传递给RenderResult的方法。

这些都是当前版本的相关片断@testing-library/react@testing-library/dom

@testing-library/dom

类型/查询

export type GetByText = (
  container: HTMLElement,
  id: Matcher,
  options?: SelectorMatcherOptions,
) => HTMLElement

export const getByText: GetByText

类型/获取元素查询

import * as queries from './queries';

export type BoundFunction<T> = T extends (
    attribute: string,
    element: HTMLElement,
    text: infer P,
    options: infer Q,
) => infer R
    ? (text: P, options?: Q) => R
    : T extends (a1: any, text: infer P, options: infer Q, waitForElementOptions: infer W) => infer R
    ? (text: P, options?: Q, waitForElementOptions?: W) => R
    : T extends (a1: any, text: infer P, options: infer Q) => infer R
    ? (text: P, options?: Q) => R
    : never;
export type BoundFunctions<T> = { [P in keyof T]: BoundFunction<T[P]> };

export type Query = (
    container: HTMLElement,
    ...args: any[]
) => Error | Promise<HTMLElement[]> | Promise<HTMLElement> | HTMLElement[] | HTMLElement | null;

export interface Queries {
    [T: string]: Query;
}

export function getQueriesForElement<T extends Queries = typeof queries>(
    element: HTMLElement,
    queriesToBind?: T,
): BoundFunctions<T>;

@testing-library/react

(可能相关,也可能不相关)
types / index.d.ts

export type RenderResult<
  Q extends Queries = typeof queries,
  Container extends Element | DocumentFragment = HTMLElement
> = {
  // ...
} & {[P in keyof Q]: BoundFunction<Q[P]>}

除了上面所做的更改之外,使每个查询的类型都通用,我更改Queryget-queries-for-element.d.ts

export type Query = <T extends HTMLElement>(
    container: HTMLElement,
    ...args: any[]
) => Error | Promise<T[]> | Promise<T> | T[] | T | null;

我几乎可以确定问题出在BoundFunction或中getQueriesForElement(),因为当我进行这些更改时(我相信37%的信心是对的),我得到一个错误:

Type 'typeof import(".../node_modules/@testing-library/dom/types/queries")' does not satisfy the constraint 'Queries'.
  Property 'getByLabelText' is incompatible with index signature.
    Type 'GetByText' is not assignable to type 'Query'.
      Type 'HTMLElement' is not assignable to type 'T | Error | T[] | Promise<T[]> | Promise<T>'.
        Type 'HTMLElement' is not assignable to type 'T'.
          'HTMLElement' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'HTMLElement'. ts(2344)

可能还有另一个问题@testing-library/react(因此,还有其他测试库软件包),但是解决此问题是第一步。

我的问题的部分原因是我实际上不了解BoundFunction正在做什么。我需要怎么做才能使maketypeof queries满足Queries约束条件?

TS游乐场

贾卡尔兹

我很确定这是TypeScript的设计限制,尽管我在GitHub上没有发现一个适用范围很窄的问题。普遍的问题是,试探性TypeScript用于检查两种类型之间的可分配性的方法不能执行真正的统一有关在TypeScript中实现这种统一的可能性的讨论,请参见microsoft / TypeScript#30134

关于您所面临的问题,我能想到的最短的例子是:

declare const genFn: <T extends 0>() => T;
const widerGenFn: <T extends 0>() => T | 1 = genFn; // error!
// Type '<T extends 0>() => T' is not assignable to type '<T extends 0>() => T | 1'.
// Type '0' is not assignable to type 'T | 1'

该函数genFn()具有一个类型参数T,该参数被限制为数字文字类型0,不包含任何函数参数,并返回type的值T该函数widerGenFn()完全相同,除了它返回类型为type的值T | 1

如果有人取代widerGenFngenFn你背后,你应该不会注意到; 如果调用widerGenFn<ABC>(),您将期望返回一个type的值ABC | 1,并且genFn返回type值的事实ABC不会打扰您,因为type的每个值也都是typeABC的值ABC | 1这意味着的类型genFn 分配给的类型widerGenFn

但事实并非如此。TypeScript抱怨是Type '<T extends 0>() => T' is not assignable to type '<T extends 0>() => T | 1'因为Type '0' is not assignable to type 'T | 1'是什么赋予了?

好吧,当比较这样的泛型函数时,编译器不会按照microsoft / TypeScript#1213的要求使用所谓的“更高种类的类型” 似乎立即将特定类型替换为T目标类型。因此,对于genFn中,编译器的变化<T extends 0>() => T,只是内容替换T约束0因此genFn被视为类型() => 0,不能分配给<T extends 0>() => T | 1

而且有一个错误。

这意味着您在尝试使用通用参数默认值时也会出错,因为这type X<T extends U = V>将要求V extends U

type GenFn = typeof genFn;
type WiderGenFn = typeof widerGenFn
type Foo<T extends WiderGenFn = GenFn> = void; // error!
// ---------------------------> ~~~~~

那么解决方法是什么?我不确定...这可能在很大程度上取决于用例。一种方法是“扩大”对所涉及的两种类型并集的约束

type Bar<T extends WiderGenFn | GenFn = GenFn> = void; // okay

(在您的情况下,它看起来像Q extends Queries | typeof queries = typeof queries

也许还有其他方法可以避免TypeScript缺乏统一性,但是看到奇怪的副作用和边缘情况突然出现,我不会感到惊讶。

操场上的代码链接

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

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

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

通过TypeScript中的另一个泛型类型保留泛型类型

来自分类Dev

依赖于Rust中另一个泛型的泛型类型

来自分类Dev

用另一个泛型扩展泛型类型

来自分类Dev

从Java中的另一个类“导入”泛型类型

来自分类Dev

将泛型类型参数限制为不是 VB.NET 中的另一个泛型类型参数

来自分类Dev

Java泛型的另一个泛型

来自分类Dev

使用有界的泛型类扩展另一个泛型类会产生未知类型

来自分类Dev

Java泛型:如何将泛型参数声明为另一个泛型参数的基本类型?

来自分类Dev

您可以指定一个泛型类型来继承另一个泛型类型并具体接口吗?

来自分类Dev

Typescript:在可选的第一个泛型之后推断泛型的类型

来自分类Dev

如何将C#泛型类型传递给另一个类

来自分类Dev

如何为一个类型设置约束,使其必须为另一个泛型类型

来自分类Dev

Scala 泛型:使用恢复实际类型来调用另一个泛型函数

来自分类Dev

Java 泛型:如何扩展另一个泛型类的泛型类

来自分类Dev

为什么我不能将一个泛型类型的实例转换为另一个实例?

来自分类Dev

对于给定的类型参数,如何声明一个特征与另一个泛型特征等效?

来自分类Dev

如何为另一个泛型类型的特征绑定表示类型参数上的特征绑定?

来自分类Dev

在Swift中将一个泛型约束到另一个泛型

来自分类Dev

泛型类型推断的 Typescript 泛型

来自分类Dev

用另一个的泛型类型制作 2 个抽象类的任何方法?

来自分类Dev

通过泛型缩小TypeScript索引类型

来自分类Dev

如何获取成员扩展或实现另一个成员的传递集合<泛型类型>的子集合?

来自分类Dev

从另一个泛型枚举初始化泛型Swift枚举?

来自分类Dev

从另一个泛型方法调用MaybeNull泛型方法

来自分类Dev

从另一个泛型枚举初始化泛型Swift枚举?

来自分类Dev

C 打印一个泛型类型向量

来自分类Dev

java中的泛型类型:如何定义一个返回多个不同类型的函数

来自分类Dev

Typescript中的默认泛型类型派生

来自分类Dev

TypeScript中泛型的深度条件类型

Related 相关文章

  1. 1

    通过TypeScript中的另一个泛型类型保留泛型类型

  2. 2

    依赖于Rust中另一个泛型的泛型类型

  3. 3

    用另一个泛型扩展泛型类型

  4. 4

    从Java中的另一个类“导入”泛型类型

  5. 5

    将泛型类型参数限制为不是 VB.NET 中的另一个泛型类型参数

  6. 6

    Java泛型的另一个泛型

  7. 7

    使用有界的泛型类扩展另一个泛型类会产生未知类型

  8. 8

    Java泛型:如何将泛型参数声明为另一个泛型参数的基本类型?

  9. 9

    您可以指定一个泛型类型来继承另一个泛型类型并具体接口吗?

  10. 10

    Typescript:在可选的第一个泛型之后推断泛型的类型

  11. 11

    如何将C#泛型类型传递给另一个类

  12. 12

    如何为一个类型设置约束,使其必须为另一个泛型类型

  13. 13

    Scala 泛型:使用恢复实际类型来调用另一个泛型函数

  14. 14

    Java 泛型:如何扩展另一个泛型类的泛型类

  15. 15

    为什么我不能将一个泛型类型的实例转换为另一个实例?

  16. 16

    对于给定的类型参数,如何声明一个特征与另一个泛型特征等效?

  17. 17

    如何为另一个泛型类型的特征绑定表示类型参数上的特征绑定?

  18. 18

    在Swift中将一个泛型约束到另一个泛型

  19. 19

    泛型类型推断的 Typescript 泛型

  20. 20

    用另一个的泛型类型制作 2 个抽象类的任何方法?

  21. 21

    通过泛型缩小TypeScript索引类型

  22. 22

    如何获取成员扩展或实现另一个成员的传递集合<泛型类型>的子集合?

  23. 23

    从另一个泛型枚举初始化泛型Swift枚举?

  24. 24

    从另一个泛型方法调用MaybeNull泛型方法

  25. 25

    从另一个泛型枚举初始化泛型Swift枚举?

  26. 26

    C 打印一个泛型类型向量

  27. 27

    java中的泛型类型:如何定义一个返回多个不同类型的函数

  28. 28

    Typescript中的默认泛型类型派生

  29. 29

    TypeScript中泛型的深度条件类型

热门标签

归档