【问题标题】:declare type with same keys but derived type using typescript generics使用 typescript 泛型声明具有相同键但派生类型的类型
【发布时间】:2020-01-04 13:09:25
【问题描述】:

为了在使用 Angular 编写单元测试时减少样板文件,我想使用 typescript 泛型的强大功能轻松地基于现有类型声明一个新类型。

例如,来自类似的类:

class BaseClass {
    member1: number;
    member2: Observable<boolean>;
    get getter1(): Observable<string> {return null};
    method1(): void {};
}

我想用这种表示法声明一个“派生”类型

type FakeClass = Fake<BaseClass>;

与此声明相对应

interface FakeClass {
    member2: Subject<boolean>;
    getter1: Subject<string>;
}

换句话说,Fake&lt;T&gt; 应该:

  • 只保留类型为Observable&lt;any&gt;的键
  • 将类型从Observable&lt;U&gt;更改为Subject&lt;U&gt;

到目前为止,我能够保留正确的键并将类型从 Observable&lt;U&gt; 更改为 Subject&lt;any&gt;

type KeysWithTypesFlags<T, U> = {
    [key in keyof T]: T[key] extends U ? key : never;
};
// KeysWithTypesFlags<SomeClass, Observable<any>> => interface {
//     member1: never;
//     member2: 'member2';
//     getter1: 'getter1';
//     method1: never;
// }

type KeysWithTypes<T, U> = KeysWithTypesFlags<T, U>[keyof T];
// KeysWithTypes<SomeClass, Observable<any>> => 'member2' | 'getter1'

type ObservableKeys<T> = KeysWithTypes<T, Observable<any>>;
// ObservableKeys<SomeClass> => 'member2' | 'getter1'

type Fake<T> = {
    [key in ObservableKeys<T>]: Subject<any>;
};
// Fake<SomeClass> => {
//     member2: Subject<any>;  // I'd like Subject<boolean>
//     getter1: Subject<any>;  // I'd like Subject<string>
// }

但我想不出一种方法来保留原始 Observable 的泛型类型。要真正通用,它应该适用于任何类型的 Observable(即,我们不能假设只有布尔值或字符串的 Observable,如示例中所示)

知道如何实现这一目标吗?

【问题讨论】:

    标签: typescript generics typescript-generics


    【解决方案1】:

    使用infer ! 在条件类型中,您可以推断出泛型类型,例如Observable&lt;infer T&gt;

    type Fake<C> = {
        [K in KeysWithTypes<C, Observable<any>>]: C[K] extends Observable<infer T> ? Subject<T> : never;
    }
    

    查看更多:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types

    【讨论】:

    • 太好了,我欠你一个。正是我想要的
    猜你喜欢
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 2016-03-17
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    相关资源
    最近更新 更多