【问题标题】:Discriminate private member union in Typescript在 Typescript 中区分私有成员工会
【发布时间】:2018-07-11 05:30:33
【问题描述】:

我在区分私人班级成员的类型方面遇到了一点问题。我正在尝试使用字符串文字访问变量v1v2,但是打字稿返回一个类型联合。我设法通过给打字稿一点“推动”来解决这个问题。坏消息是它只适用于公众成员。请参阅下面的示例:

class Test {
    private v1: string;
    private v2: number;
    v3: string;
    v4: number;
    private v5: string;
    private v6: number;

    // Works for all members, but does not discriminate union
    get12(what: 'v1' | 'v2') {
        return this[what];
    }

    // Works only for public members
    get34<T extends 'v3' | 'v4'>(what: T) {
        return this[what];
    }

    // Explicit overload works, but it defeats the purpose of being lazy
    get56(what: 'v5'): string;
    get56(what: 'v6'): number;
    get56(what: 'v5' | 'v6') {
        return this[what];
    }
}

let myTest = new Test();
myTest.get12('v1'); // returns "string | number" type
myTest.get34('v3'); // returns "string" type
myTest.get56('v5'); // returns "string" type

有人知道某种解决方法吗?

编辑: 为了澄清,我正在寻找一个惰性/通用的解决方案。还有其他方法可以实现我想要的,但是它们都需要我维护它们以防变量类型发生变化(例如,显式重载)。

【问题讨论】:

  • 显式重载有用吗?
  • 你检查过类型保护吗? basarat.gitbooks.io/typescript/docs/types/…那么你至少可以在事后缩小类型
  • @vincecampanale 在这种情况下我真的不需要类型保护。显式重载会起作用,但是我希望有人知道某种方法来欺骗打字稿以区分联合,就像我为公共成员所做的那样。

标签: typescript


【解决方案1】:

Bleggh,这似乎是 TypeScript 的 design limitation,在某些情况下,您不能在具有私有属性的情况下使用索引访问。不知道如何最好地导航。

这里有一些“有效”的东西,但我不建议你真的这样做

//@ts-ignore
type UnsafeIndexed<T, K extends string> = T[K]

上面是一个故意的错误类型别名,它要求编译器进行索引访问,即使它不能确定这样的事情是否会起作用。看看吧:

type Foo = { bar: string, baz: number };
type FooBar = UnsafeIndexed<Foo, "bar">; // string
type FooBaz = UnsafeIndexed<Foo, "baz">; // number
type FooBad = UnsafeIndexed<Foo, "nope">; // any

现在你可以这样做了:

class Test {
    private v1: string;
    private v2: number;

    get<K extends 'v1' | 'v2'>(what: K): UnsafeIndexed<this,K> {
        return (this as any)[what];
    }
}

请注意,您必须执行(this as any),因为this[what] 仍然会引发编译器错误。测试一下:

let myTest = new Test();
const v1 = myTest.get('v1'); // string
const v2 = myTest.get('v2'); // number

好的,正如我所说,这“有效”。但我不想要那种感人的生产代码。我不知道是否有一个不那么邪恶的通用解决方法。就个人而言,我要么只使用公共属性,要么使用重载。您的里程可能会有所不同。

希望对您有所帮助。祝你好运!

【讨论】:

  • 有一种方法可以使UnsafeIndexed 安全(有点)。看看这个:get12(what: 'v1' | 'v2'): UnsafeIndexed&lt;this, typeof what&gt; { return this[what]; }。如果 what 文字没有有效属性,则将抱怨隐含的任何内容。我想我会使用这个解决方案。如果您可以编辑您的答案以包含此内容,我将接受它作为答案。
  • 但是当你调用它时它只会返回string | number,这对你原来的get12()没有任何改进。我不明白你为什么要我把它包括在内。你能仔细检查一下吗?
  • 确实,它似乎有效,但同时我在 VSCODE IDE 中切换了 typescript 版本。这可能对我造成了这种误报。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-20
  • 2022-01-08
  • 1970-01-01
  • 2012-09-24
相关资源
最近更新 更多