首页 > 解决方案 > 我将如何构造类型来表示这一点?

问题描述

假设我有一个界面

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

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

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

并且

我目前有


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
  });
}

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

错误是:

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

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

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

edit2:基于对此的一些评论,我对此进行了更深入的思考,并提出了一个更精炼的示例: 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,但对于我的实际需要,我需要能够从同一个函数返回多个变体。

标签: typescripttypescript-typings

解决方案


它可能是这样的:

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());

推荐阅读