如何将Typescript的声明与从模块导入的接口合并使用? [英] How can I use Typescript's declaration merging with an interface imported from a module?

查看:288
本文介绍了如何将Typescript的声明与从模块导入的接口合并使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

https://www.typescriptlang.org/docs/handbook/declaration -merging.html

上面的链接提供有关声明与接口合并的信息.我希望能够通过具有通用组件的接口来做到这一点.我目前正在使用Typescript 3.0.3.

这可以满足我的要求,但是我不明白为什么声明合并不能做同样的事情.

interface MyRouteComponentProps<P, C extends StaticContext = StaticContext> extends RouteComponentProps<P, C> {
    loadCandidateFromQueryParam: (candidateId: number) => void
}

class CandidateDetailContainer extends React.Component<MyRouteComponentProps<RouteMatchProps>, {}> {

    public componentWillMount() {
        this.props.loadCandidateFromQueryParam(Number(this.props.match.params.candidateId));
    }

为什么这行不通?

interface RouteComponentProps<P, C extends StaticContext = StaticContext> {
    loadCandidateFromQueryParam: (candidateId: number) => void
}

class CandidateDetailContainer extends React.Component<RouteComponentProps<RouteMatchProps>, {}> {

似乎完全覆盖了RouteComponentProps的整个定义,而不是合并它们.我收到与从未使用过的P和C有关的错误(如果定义被合并,那么我希望这些错误会消失,因为它们已在主要定义中使用).然后我收到一个关于匹配"字段不存在的错误.再次,原始定义中存在另一个字段.

作为参考,这是我尝试与之合并的原始定义.

export interface RouteComponentProps<P, C extends StaticContext = StaticContext> {
  history: H.History;
  location: H.Location;
  match: match<P>;
  staticContext: C | undefined;
}

解决方案

实际上,在您的第二个示例中,当我添加导入时,我假设您必须具有:

import * as React from "react";
import { RouteComponentProps, StaticContext } from "react-router";

导入RouteComponentProps时出现错误.

您不能通过声明相同名称的本地符号来将内容合并到导入的符号(接口,名称空间等)中.这将是一个错误,或者将阴影化导入的符号.要合并定义,它们必须在同一范围内.在将内容合并到模块的符号中的情况下,可以使用模块扩充将定义放入原始模块的范围内:

declare module "react-router" {
    interface RouteComponentProps<Params, C extends StaticContext = StaticContext> {
        loadCandidateFromQueryParam: (candidateId: number) => void
    }
}

(使它成为模块扩充而不是模块声明的原因是它嵌套在另一个模块中.我知道这很晦涩.)请注意,类型参数的名称必须与原始接口中的名称相同. /p>

https://www.typescriptlang.org/docs/handbook/declaration-merging.html

The above link provides information on declaration merging with interfaces. I'd like to be able to do that with an interface that's got a generic component. I'm currently using Typescript 3.0.3.

This does what I want, but I don't understand why I can't do the same thing with declaration merging.

interface MyRouteComponentProps<P, C extends StaticContext = StaticContext> extends RouteComponentProps<P, C> {
    loadCandidateFromQueryParam: (candidateId: number) => void
}

class CandidateDetailContainer extends React.Component<MyRouteComponentProps<RouteMatchProps>, {}> {

    public componentWillMount() {
        this.props.loadCandidateFromQueryParam(Number(this.props.match.params.candidateId));
    }

Why doesn't this work?

interface RouteComponentProps<P, C extends StaticContext = StaticContext> {
    loadCandidateFromQueryParam: (candidateId: number) => void
}

class CandidateDetailContainer extends React.Component<RouteComponentProps<RouteMatchProps>, {}> {

It seems to completely override the entire definition for RouteComponentProps instead of merging them. I get errors related to P and C never being used (if the definitions were merged then I would expect those errors to go away because they're used in the primary definition). And then I get an error about "match" field not being there. Again, another field that was present in the original definition.

For reference here's the original definition that I'm trying to merge with.

export interface RouteComponentProps<P, C extends StaticContext = StaticContext> {
  history: H.History;
  location: H.Location;
  match: match<P>;
  staticContext: C | undefined;
}

解决方案

In fact, in your second example, when I add the imports that I assume you must have:

import * as React from "react";
import { RouteComponentProps, StaticContext } from "react-router";

I get an error on the import of RouteComponentProps.

You can't merge content into an imported symbol (interface, namespace, etc.) by declaring a local symbol of the same name; either this will be an error or it will shadow the imported symbol. To merge definitions, they must be in the same scope. In the case of merging content into a symbol from a module, you can use a module augmentation to put your definition in the scope of the original module:

declare module "react-router" {
    interface RouteComponentProps<Params, C extends StaticContext = StaticContext> {
        loadCandidateFromQueryParam: (candidateId: number) => void
    }
}

(What makes this a module augmentation rather than a module declaration is that it is nested inside another module. Obscure, I know.) Note that the names of the type parameters have to be the same as in the original interface.

这篇关于如何将Typescript的声明与从模块导入的接口合并使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆