【问题标题】:Typescript: constructor overloading打字稿:构造函数重载
【发布时间】:2017-11-29 08:05:08
【问题描述】:

我需要将这些 Java 构造函数重载转换为 Typescript:

public QueryMixin() {
    this(null, new DefaultQueryMetadata(), true);
}

public QueryMixin(QueryMetadata metadata) {
    this(null, metadata, true);
}

public QueryMixin(QueryMetadata metadata, boolean expandAnyPaths) {
    this(null, metadata, expandAnyPaths);
}

public QueryMixin(T self) {
    this(self, new DefaultQueryMetadata(), true);
}

public QueryMixin(T self, QueryMetadata metadata) {
    this(self, metadata, true);
}

public QueryMixin(T self, QueryMetadata metadata, boolean expandAnyPaths) {//...}

我已经尝试创建这些构造函数来看看那里,但我无法弄清楚如何获得它......

有什么想法吗?

constructor();  <<<1>>>
constructor(metadata: QueryMetadata);
constructor(metadata: QueryMetadata, expandAnyPaths: boolean);
constructor(self: T);
constructor(self: T, metadata: QueryMetadata);
constructor(selfOrMetadata: T | QueryMetadata, expandAnyPaths: boolean) {
    this.self = selfOrMetadata;  <<< PROBLEM HERE
    this.metadata = selfOrMetadata;  <<< PROBLEM HERE
    this.expandAnyPaths = expandAnyPaths;
}

&lt;&lt;&lt;1&gt;&gt;&gt; 我收到这条编译消息:

重载签名与函数实现不兼容。

【问题讨论】:

  • 在重载列表之后,您必须提供实际的实现签名,它必须(粗略地说)它之前的所有重载的交集。所以在这种情况下,您必须在底部添加:constructor(selfOrMetaData?: T | QueryMetadata ...) 等等。或者,您可以在那时放弃任何类型安全的假装,然后执行constructor(,,,args: any[])
  • 我添加了最后一个类似 java 的构造函数实现。我不太清楚如何区分selfOrMetadata 是否可以分配给selfmetadata
  • 您需要将两个参数都设为可选 (selfOrMetaData?),因为至少有一个重载没有提供任何参数。此外,您的第二个参数同样需要是第二个位置中所有可能的参数类型的联合。 expandAnyPathsOrMetadata?: boolean | QueryMetadata.
  • 你介意给我一个答案吗?

标签: typescript typescript2.0


【解决方案1】:

您可以实现您所追求的构造函数重载,但您必须执行一些类型检查才能实现...我不知道QueryMetadata 是什么样的,但您应该能够从中得到这个想法这个独立的例子。

我正在使用自定义类型保护来分隔这些联合类型:

interface QueryMetadata {
    metadata: string;
}

function isQueryMetadata(obj: any): obj is QueryMetadata {
    return (obj && obj.metadata);
}

class Example<T> {

    private metadata: QueryMetadata;
    private self: T;
    private expandAnyPaths: boolean;

    constructor(metadata: QueryMetadata);
    constructor(metadata: QueryMetadata, expandAnyPaths: boolean);
    constructor(self: T);
    constructor(self: T, metadata: QueryMetadata);
    constructor(selfOrMetadata: T | QueryMetadata, expandOrMetadata: boolean | QueryMetadata = false) {
        if (isQueryMetadata(selfOrMetadata)) {
            this.metadata = selfOrMetadata;
        } else {
            this.self = selfOrMetadata;
        }

        if (isQueryMetadata(expandOrMetadata)) {
            this.metadata = expandOrMetadata;
        } else {
            this.expandAnyPaths = expandOrMetadata;
        }
    }
}

工厂方法替代

如果您正在编写新的东西,您可能更喜欢使用工厂方法来构造您的类...

interface QueryMetadata {
    metadata: string;
}

class Example<T> {

    private metadata: QueryMetadata;
    private self: T;
    private expandAnyPaths: boolean;

    protected constructor() { }

    static fromMetadata<T>(metadata: QueryMetadata, expandAnyPaths: boolean = false) {
        const example = new Example<T>();
        example.metadata = metadata;
        example.expandAnyPaths = expandAnyPaths;
    }

    static fromSelf<T>(self: T, expandAnyPaths: boolean = false) {
        const example = new Example<T>();
        example.self = self;
        example.expandAnyPaths = expandAnyPaths;
    }
}

const example1 = Example.fromSelf('Some Value');
const example2 = Example.fromSelf('Some Value', true);
const example3 = Example.fromMetadata({ metadata: 'val' });
const example4 = Example.fromMetadata({ metadata: 'val' }, true);

【讨论】:

  • 我创建了一个新帖子,以便在 here 上创建一个相关问题。不同的是,最后一个构造函数必须能够收集所有的可能性。
猜你喜欢
  • 2017-08-03
  • 2020-05-20
  • 2019-11-15
  • 2018-05-22
  • 1970-01-01
  • 2016-09-04
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多