如何根据条件将可选属性设置为必填?

时间:2019-03-28 04:22:49

标签: typescript

这是我的代码:

interface IOptions {
  clientId: string;
  token: string;
}

interface IComponent {
  name: string;

  parent?: { name: string };
}

async function createComponent(opts?: IOptions): Promise<IComponent> {
  const component: IComponent = { name: '' };

  if (opts) {
    component.parent = { name: `${opts.clientId}-${opts.token}` };
  }

  return component;
}

async function main() {
  const { name, parent } = await createComponent();

  console.log(parent.name);
}

如果parent函数中存在IComponent,我想使opts接口的createComponent可选属性成为必需属性。

目前,在parent.name函数中使用main时出现错误。

  

对象可能是'undefined'.ts(2532)

我希望createComponent函数的返回值接口类似于:Promise<IComponentRequired>如果存在opts,并且返回Promise<IComponent>如果不存在opts。像这样:

interface IComponentRequired {
  name: string;

  parent: { name: string };
}

我的想法是IComponent => Required<T> => IComponentRequired

更新

这是我的尝试,但是没有用。

async function otherMain() {
  const opts: IOptions = { clientId: '123', token: '321' };
  const component: Required<IComponent> = await createComponent(opts);

  console.log(component.parent.name);
}

错误:

  

类型“ IComponent”不可分配给类型“必需”。     属性“父级”的类型不兼容。       输入'{name:string; } |未定义”不能分配给类型“ {name:string; }'。         类型'undefined'不能分配给类型'{name:string; }'。ts(2322)

1 个答案:

答案 0 :(得分:0)

您可以使用重载来返回所需版本或该属性为可选的版本:

interface IOptions {
    clientId: string;
    token: string;
}

interface IComponent {
    name: string;

    parent?: { name: string };
}

async function createComponent(): Promise<IComponent>
async function createComponent(opts: IOptions): Promise<Required<IComponent>>
async function createComponent(opts?: IOptions): Promise<IComponent> {
    const component: IComponent = { name: '' };

    if (opts) {
        component.parent = { name: `${opts.clientId}-${opts.token}` };
    }

    return component;
}

async function main() {
    const opts: IOptions = { clientId: '123', token: '321' };
    const component: Required<IComponent> = await createComponent(opts);

    console.log(component.parent.name);
}