程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了TypeScript - 如果扩展其他东西,类泛型类型太窄,如果不扩展任何东西,则不是大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决TypeScript - 如果扩展其他东西,类泛型类型太窄,如果不扩展任何东西,则不是?

开发过程中遇到TypeScript - 如果扩展其他东西,类泛型类型太窄,如果不扩展任何东西,则不是的问题如何解决?下面主要结合日常开发的经验,给出你关于TypeScript - 如果扩展其他东西,类泛型类型太窄,如果不扩展任何东西,则不是的解决方法建议,希望对你解决TypeScript - 如果扩展其他东西,类泛型类型太窄,如果不扩展任何东西,则不是有所启发或帮助;

我有 Item<T>StrictItem<T extends Something> 之类的课程。如果我像 Item('a') 一样初始化前者,它将被视为 Item<string>,而 StrictItem<'a'> 将被视为 StrictItem<'a'>

  1. 为什么对泛型施加约束会导致这些差异?似乎没有关系。
  2. 有没有办法更改 StrictItem 定义,使 StrictItem('a') 变为 StrictItem<string>,同时仍保留对泛型的约束?

Playground

interface PlainObject<T> { [index: string ]: T}

type ItemValue =
  boolean |
  number |
  string |
  ItemValue[] |
  { [index: string ]: ItemValue } |
  null;

class Item<T> {
    private value: T;
    constructor(value: T) {
        this.value = value;
    }
    public set(value: T) {
        this.value = value;
    }
}

// This one puts restrictions on the generic
class StrictItem<T extends ItemValue> extends Item<T> {
}

// 1. Why does the error seen in item2 does not occur here?
let item1 = new Item('a');
item1.set('b');
item1.set(0); // error

// 1. Can StrictItem deFinition be modifIEd to implictly infer a more
// general type ('string') in this case (without using any type for T)?
// Or is explicitly defining the type of passed value the only way (see item3)?
let item2 = new StrictItem('a');
item2.set('b'); // error

let item3 = new StrictItem('a' as string);
item3.set('b');

解决方法

为什么对泛型施加约束会导致这些差异?好像没有关系。

我相信,当您执行 <T> 时,您会告诉编译器,“只需使用通常会推断出的任何内容。而在 let foo = 'bar' 中,foo 被推断为 string。没有额外的符号,这是默认的。

然而,<T extends ItemValue> 的说法略有不同。这告诉编译器“T 是一种扩展 ItemValue 的类型,这意味着它可能是一个更具体的子类型。”在这种情况下,它会推断出它所能推断出的最具体的类型。

所以如果你限制一个泛型,你应该期望它是一个超级特定的类型。通常,这就是您想要的。


有没有办法更改 StrictItem 定义,因此 StrictItem('a') 将是 StrictItem<string>,同时仍然保留对泛型的约束?

我不知道。但这通常不是问题。很难从人为的示例中建议采取行动,但通常情况下,您实际上并没有将字符串文字硬编码为这样的类型。相反,数据可能来自其他一些数据源、函数或变量。

在这种情况下,您可以简单地将类型为 string 的变量传递给它,它的工作方式与您预期的一样。

let item4Data = getSomeString() // returns string
let item4 = new StrictItem(item4Data) // StrictItem<string>

如果你真的只想传入一个文字,你总是可以在使用类型时显式传入一个类型参数。这是类型安全的,因为根据您提供的类型检查了参数的类型。

let item5 = new StrictItem<string>('a')
item5.set('b') // works

let item6 = new StrictItem<string>(123) // type error
,

这里有一个解决方案:

interface PlainObject<T> { [index: string]: T }

type ItemValue =
    | boolean
    | number
    | string
    | ItemValue[]
    | { [index: string]: ItemValue }
    | null;

class Item<T> {
    private value: T;
    constructor(value: T) {
        this.value = value;
    }
    public set(value: T) {
        this.value = value;
    }
}

type Infer<T> = T extends infer R ? R : never

// This one puts restrictions on the generic
class StrictItem<T extends ItemValue> extends Item<Infer<T>> { }

let item2 = new StrictItem('a');
item2.set('b'); // ok

您可以只使用 infer 来获取更通用的类型并对其进行包装

更新 作为替代解决方案,您可以添加具有默认值的第二个通用参数:

interface PlainObject<T> { [index: string]: T }

type ItemValue =
    | boolean
    | number
    | string
    | ItemValue[]
    | { [index: string]: ItemValue }
    | null;

class Item<T> {
    private value: T;
    constructor(value: T) {
        this.value = value;
    }
    public set(value: T) {
        this.value = value;
    }
}

type Infer<T> = T extends infer R ? R & ItemValue : never

// This one puts restrictions on the generic
class StrictItem<T,R = Infer<T>> extends Item<R> { }

let item2 = new StrictItem('a');
item2.set('2'); // ok

大佬总结

以上是大佬教程为你收集整理的TypeScript - 如果扩展其他东西,类泛型类型太窄,如果不扩展任何东西,则不是全部内容,希望文章能够帮你解决TypeScript - 如果扩展其他东西,类泛型类型太窄,如果不扩展任何东西,则不是所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: