【问题标题】:typescript typing encapsulation打字稿打字封装
【发布时间】:2020-09-28 15:05:15
【问题描述】:

在下面的例子中,我试图描述一个复杂的打字稿类型,我想在以后使用FinalType。问题是,由于它的复杂性,这种类型需要声明污染页面 IntermediaryType/IntermediaryType2 的中间类型。

Playground

type IntermediaryType = {
  decisiveKey: true,
  mutatedKey: (params: any) => void,
} | {
  decisiveKey: false,
  mutatedKey?: false,
}

interface IntermediaryType2 {
  foo?: string,
  bar?: boolean,
}

type FinalType = IntermediaryType & IntermediaryType2;

const Foo = (param: FinalType) => {}

Foo({
  decisiveKey: true,
  mutatedKey: () => {},
});

我的问题是,有没有办法让中间类型无法访问,只允许使用FinalType


我看到您可以使用 方括号 将部分代码括起来,例如:

{
  type IntermediaryType = {
    decisiveKey: true,
    mutatedKey: (params: any) => void,
  } | {
    decisiveKey: false,
    mutatedKey?: false,
  }

  interface IntermediaryType2 {
    foo?: string,
    bar?: boolean,
  }

  type FinalType = IntermediaryType & IntermediaryType2;
}

const Foo = (param: FinalType) => {}

Foo({
  decisiveKey: true,
  mutatedKey: () => {},
});

但是我显然无法访问FinalType。我尝试过使用returnexport,但都不起作用。

理想的情况是这样的:

type FinalType = {
  type IntermediaryType = {
    decisiveKey: true,
    mutatedKey: (params: any) => void,
  } | {
    decisiveKey: false,
    mutatedKey?: false,
  }

  interface IntermediaryType2 {
    foo?: string,
    bar?: boolean,
  }

  return IntermediaryType & IntermediaryType2;
}

const Foo = (param: FinalType) => {}

Foo({
  decisiveKey: true,
  mutatedKey: () => {},
});

有什么线索吗?



使用@Aluan Haddad 的答案,目前我能做到的最好的是:

namespace _ {
    type IntermediaryType = {
        decisiveKey: true,
        mutatedKey: (params: any) => void,
    } | {
        decisiveKey: false,
        mutatedKey?: false,
    }

    interface IntermediaryType2 {
        foo?: string,
        bar?: boolean,
    }

    export type FinalType = IntermediaryType & IntermediaryType2;
}; type FinalType = _.FinalType;

const Foo = (param: FinalType) => {}

Foo({
  decisiveKey: true,
  mutatedKey: () => {},
});

我很想在上面添加一些语法糖!

【问题讨论】:

  • 我认为你应该通过不同的文件来组织你的架构,在这种情况下,只导出 FinalType。通过这种方式,您将拥有一个包含所有中间类型和最终类型的文件,但是,只有最终类型可以在外部文件中使用。
  • 这是一个在 90% 的情况下都很好的架构建议。但是当您键入使用稍微修改的现有类型的私有方法时;我几乎看不到放入外部文件的价值。

标签: javascript typescript typescript-typings encapsulation


【解决方案1】:

你真正想要做的,为类型引入任意范围,可以通过 TypeScript 命名空间来完成。

declare namespace myNamespace {
  type IntermediaryType = {
    decisiveKey: true,
    mutatedKey: (params: any) => void,
  } | {
    decisiveKey: false,
    mutatedKey?: false,
  }

  interface IntermediaryType2 {
    foo?: string,
    bar?: boolean,
  }

  export type FinalType = IntermediaryType & IntermediaryType2;
}

const Foo = (param: myNamespace.FinalType) => {}

Foo({
  decisiveKey: true,
  mutatedKey: () => {},
});

但是,如果您正在编写现代代码并因此使用模块,则几乎总是应该避免使用命名空间。幸运的是,如果您使用的是模块,则解决方案会更加简单;不要导出中间类型。

type IntermediaryType = {
  decisiveKey: true,
  mutatedKey: (params: any) => void,
} | {
  decisiveKey: false,
  mutatedKey?: false,
}

interface IntermediaryType2 {
  foo?: string,
  bar?: boolean,
}

export type FinalType = IntermediaryType & IntermediaryType2;

export const Foo = (param: FinalType) => {}

Foo({
  decisiveKey: true,
  mutatedKey: () => {},
});

【讨论】:

  • 命名空间可以解决问题,但使用起来仍然不方便。另外重新声明类型将使其成为type FinalType = namespace.FinalType;。关于第二个建议,在本地文件范围内,导出并不能解决任何问题。感谢您的回答
  • 如果全部用于单个文件中的作用域,那么命名空间是合适的,即使在模块中也是如此。这是一个权衡。
【解决方案2】:

我不确定你的序言

由于它的复杂性,这种类型需要声明中间类型

这编译

type FinalType = (
  | {
      decisiveKey: true;
      mutatedKey: (params: any) => void;
    }
  | {
      decisiveKey: false;
      mutatedKey?: false;
    }
) & {
  foo?: string;
  bar?: boolean;
};

const Foo = (param: FinalType) => {};

Foo({
  decisiveKey: true,
  mutatedKey: () => {}
});

希望这会有所帮助。

【讨论】:

  • 感谢您的回答。所以你的解决方案是抑制 typeinterface 关键字。在某些情况下可能是一个解决方案。但是如果应用到大而深的类型上似乎有点复杂
  • 公开构建公开的所有内容(在您的情况下为类型)所需的所有内容是 TypeScript 的性质。如果您不想公开任何中间类型,则只需使用本机类型。
猜你喜欢
  • 1970-01-01
  • 2021-07-27
  • 2020-01-31
  • 2023-03-07
  • 2018-06-21
  • 2019-07-29
  • 2022-01-25
  • 2015-12-16
  • 2016-05-08
相关资源
最近更新 更多