【问题标题】:How would I structure types to represent this?我将如何构造类型来表示这一点?
【发布时间】:2020-03-02 01:24:04
【问题描述】:

假设我有一个界面

interface FooBranchState {
  a: string;
  b: FooDiscriminator;
}

type FooDiscriminator = (value: any) => FooState;

我想将FooState 定义为表示以下内容的类型或接口:

  • SingleFooBranchStateImpl 的一个实例
  • SingleFooBranchStateImpl 的实例数组

还有

  • 返回上述任何一项的函数
  • 一个向上述任何一个返回承诺的函数

我现在有


export type FooState = FooEndState | FooBranchState

export type FooDiscriminator = (value: any) => FooState;

export type FooEndState = null;

export type FooBranchState = SingleFooBranchState | (SingleFooBranchState[])

export interface SingleFooBranchStateImpl {
  foo: any;
  next: FooDiscriminator;
}

export type SingleFooBranchStateFunction = () => SingleFooBranchStateImpl 
export type SingleFooBranchState = SingleFooBranchStateImpl | SingleFooBranchStateFunction;


function test(value: FooState) {
  console.log(value);
}

function getSingle(): FooState {
  return { 
    foo: 1,
    next: () => null
  };
}

function getNull(): FooState {
  return null;
}


function getArray(): FooState {
  return [
    getSingle(),
    getSingle()
  ];
}

function getFunctionSingle(): FooState {
  return () => ({
    foo: 2,
    next: () => null
  });
}

function getFunctionArray(): FooState {
  return () => ([{
    foo: 3,
    next: () => null
  }]);
}

function getPromise(): FooState {
  return Promise.resolve({
    foo: 4,
    next: () => null
  });
}

但是将FooState[] 分配给FooState 需要强制转换为FooState,否则我会收到以下错误。这让我觉得我的定义有些不正确。

错误是:

类型“FooBranchState[]”不可分配给类型“FooBranchState”。 类型“FooBranchState[]”不可分配给类型“SingleFooBranchState[]”。 类型“FooBranchState”不可分配给类型“SingleFooBranchState”。 类型“SingleFooBranchState[]”不可分配给类型“SingleFooBranchState”。 类型“SingleFooBranchState[]”不可分配给类型“SingleFooBranchStateFunction”。 类型 'SingleFooBranchState[]' 与签名 '(): SingleFooBranchStateImpl' 不匹配。

编辑: 更正了原始问题中的一些拼写错误(我正在将我的实际代码简化为一个精简的示例并犯了几个错误)。

根据要求,这是一个示例:https://stackblitz.com/edit/typescript-xyag2s

编辑2: 基于这方面的一些 cmets,我对此进行了更深入的思考,并提出了一个更精炼的例子: http://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=18&pc=1#code/C4TwDgpgBAogtmUUC8UB2BXANlg3AWAChRIoANAJhSgGdgAnASzQHMDjxozrKoAfchQDaAXX6wEodkSIAzDGgDGwRgHs0UFhGABlZiywQAFAEoAXOSgBvKAHpbUAO6r6AaxpEoUetoz0NAOQAFowB7AC+MoTySirqmtoActhYphbcNvZOLu6e3r7+6CkRUTHKahpawACC9PQAhiBpljZ2DhB1LgA0UABGEIr1GDRcUIMa-UU4Pb0YwIJj9WgB85OYOHk+wH4aQl77B4deWdzjfdBLUPV1jVCqsoIzc1caZKLZ2AAmV1g0qmPqYD1Zh5LxVPSsQymI6HLJ7dZYHoBOhMVgBKAiPIiEqEOQKcrxKq1BogCjNDJtbJuDyELxbHZQIQrCB0ALYojhIA

type Empty = null;
type X2 = string;
type X = X2 | X2[] | Empty;


function getSingle(): X { // works
  return 'hi';
}

function getNull(): X { // works
  return null;
}

function getArray(): X {  // error, because X can be null, but X2 can't be null
  return [                // X can be an array of X2, but an X[] would also contain
    getSingle()           // [ null, 'string' ]
  ];
}

function getArray2(): X { // works
  return ['test'];
}

在简单的示例中,将 getSingle 声明为 X2 几乎是有意义的,但对于我的实际需要,我需要能够从同一个函数返回多个变体。

【问题讨论】:

  • “[...] 一种类型或接口,表示以下内容:[...] Foo 的实例”。我在您的代码中根本没有看到任何名为 Foo 的类型。
  • 请考虑编辑代码以构成minimal reproducible example,如How to Ask 指南中所述,这是一个好问题。现在导致错误的代码丢失了,所以我不确定问题是什么。或者更确切地说,我知道您不能将FooState[] 值分配给FooState 类型的变量,但该错误与您的代码及其描述一致。我也不知道什么是“Foo 的实例”,所以这可能是其中的一部分。无论如何,让其他人轻松展示您的问题(并且只有您的问题)的示例会有所帮助。祝你好运!
  • @jcalz 请查看我的编辑。我提供了一个例子:stackblitz.com/edit/typescript-xyag2s
  • 代码链接很棒,但代码也应该在问题本身中。 (见How to Ask,“不是每个人都可以访问外部网站,链接可能会随着时间的推移而中断”)
  • 我也不确定如何解释“我想将FooState 定义为一种类型......代表......FooState 的一个实例”。这是什么意思?

标签: typescript typescript-typings


【解决方案1】:

可能是这样的:

export type Foo = any;

export type FooState = null | Foo | Array<Foo> | FooDistriminator | FooDistriminatorPromise;

export type FooDistriminator = (value: any) => null | Foo | Array<Foo>;

export type FooDistriminatorPromise = (value: any) => Promise<null | Foo | Array<Foo>>;

编辑:在您的 stackblitz 问题中,您的函数类型似乎与传递值和返回值有关。我让它像这样工作:

export type FooState = FooEndState | FooBranchState

export type FooDiscriminator = (value: any) => FooState;

export type FooEndState = null;

export type FooBranchState = SingleFooBranchState | Array<SingleFooBranchState> | Promise<SingleFooBranchStateImpl>

export interface SingleFooBranchStateImpl {
    foo: any;
    next: FooDiscriminator;
}

export type SingleFooBranchStateFunction = () => SingleFooBranchStateImpl
export type SingleFooBranchState = SingleFooBranchStateImpl | SingleFooBranchStateFunction;


function test(value: FooState) {
    console.log(value);
}

function getSingle(): SingleFooBranchStateImpl {
    return {
        foo: 1,
        next: () => null
    };
}

function getNull(): FooState {
    return null;
}


function getArray(): Array<SingleFooBranchState> {
    return [
        getSingle(),
        getSingle()
    ];
}

function getFunctionSingle(): FooState {
    return () => ({
        foo: 2,
        next: () => null
    });
}


function getPromise(): Promise<SingleFooBranchStateImpl> {
    return Promise.resolve({
        foo: 4,
        next: () => null
    });
}

test(null);
test(getSingle());
test(getNull());
test(getArray());
test(getFunctionSingle());
test(getPromise());

【讨论】:

  • 只要 type Foo = any 就可以工作,但是如果我尝试充实该类型,我会得到与以前相同的错误。请查看我的编辑以获取代码示例
  • 我看到了您的更新,看起来您遇到了与我类似的问题。您必须将 getArray() 声明为返回 Array。似乎(以及我想要实现的目标)FooState 可以是 FooBranchState,可以是 Array,因此,传递地,FooState 可以是 Array,并且通过身份,Array 是 FooState .所以你应该可以将 getArray 函数声明为 FooState,对吧?
  • 正确。您可以将 getArray() 的返回值从 Array 替换为 FooState ,它将成功编译。
  • 不适合我。它给了我一个与最初类似的错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 2016-10-08
  • 2012-12-03
相关资源
最近更新 更多