首页 > 解决方案 > 以一种方式实现接口,当一个类实现它时,它**必须**实现接口的所有属性,无论是可选的还是非可选的

问题描述

我想以一种方式实现接口,当一个类实现它时,它必须实现接口的所有属性,无论是可选的还是非可选的。

如果我有

interface Person {
  name: string,
  address?: string,
}



class Fisherman implements Person {
  name: string;
  fishingRodColor: string;
  // and any more properties I want
}

打字稿不会引发错误,没关系Fisherman不实现address,因为它是可选的,但我确实希望它引发错误,我希望它强制我将Fisherman类作为这两个选择之一:

class Fisherman implements Person {
  name: string;
  address?: string;
  fishingRodColor: string;
  // and any more properties I want
}

或者

class Fisherman implements Person {
  name: string;
  address: string;
  fishingRodColor: string;
  // and any more properties I want
}

两者都应该被允许,并且至少应该要求其中一种实现。

如果我只是简单地编写我的Person界面而address不是可选的

interface Person {
  name: string,
  address: string,
}

它不允许我编写我希望它允许我的这个类:

class Fisherman implements Person {
  name: string;
  address?: string;
  fishingRodColor: string;
  // and any more properties I want
}

因为它会说address不能是可选的,因为它在Person界面中不是可选的。

编辑:我感谢您的帮助,但我对解决方案的另一个需要是对于我的用例,如果address是可选的,我希望能够声明这个const对象:

const fisherman: Fisherman: {
  name: 'George'
  fishingRodColor: 'Red'
}

但是如果address: string | undefined,typescript 仍然会引发一个错误,说fishermanmust have the property address。打字稿要我这样做:

const fisherman: Fisherman: {
  name: 'George'
  fishingRodColor: 'Red'
  address: undefined
}

但我不想(而且我认为我也不能在新的 Mongo 版本中,因为 undefined 已被弃用)将其中未定义的字段推送到我的数据库中。

我可以在插入数据库之前做一些变通方法,比如undefineds在插入数据库之前删除,但是对于这个用例来说,使用接口可能不值得。

标签: typescript

解决方案


您可以将所有带有类型的可选属性转换TT | undefined

type Complete<T> = {
    [P in keyof Required<T>]: Pick<T, P> extends Required<Pick<T, P>> ? T[P] : (T[P] | undefined);
}

请参阅https://medium.com/terria/typescript-transforming-optional-properties-to-required-properties-that-may-be-undefined-7482cb4e1585

在您的示例中:

class FishermanError implements Complete<Person> {
  name: string;
  fishingRodColor: string;
  // error: Property 'address' is missing
}

class Fisherman implements Complete<Person> {
  name: string;
  fishingRodColor: string;
  address: string
  // ok 
}

class Fisherman2 implements Complete<Person> {
  name: string;
  fishingRodColor: string;
  address: string | undefined
  // ok  
}

操场


推荐阅读