简体   繁体   中英

The intersection '... & ...' was reduced to 'never' because property '...' has conflicting types in some constituents

I have a two classes defined as following:

class FirstClass {
  values: FirstValuesType = {} as FirstValuesType;

  setValues(values: FirstValuesType): void {
    this.values = { ...values };
  }
}

class SecondClass {
  values: SecondValuesType = {} as SecondValuesType;

  setValues(values: SecondValuesType): void {
    this.values = { ...values };
  }
}

interface CommonValuesType {
    id: number;
    property1: string;
    property2: string;
}

enum FirstReasonEnum {
    A, B, C
}

enum SecondReasonEnum {
    X, Y, Z
}

interface FirstValuesType extends CommonValuesType {
  reason: FirstReasonEnum;

}

interface SecondValuesType extends CommonValuesType {
  reason: SecondReasonEnum;
}

And then I defined a constant which can be one of the classes as following:

const model: FirstClass | SecondClass;

When I call setValues like this:

model.setValues(newValues);

I get the following ts error:

  Argument of type '{ id: number; property1: string; property2: string; reason: FirstReasonEnum; }' is not assignable to parameter of type 'never'.
  The intersection 'FirstValuesType & SecondValuesType' was reduced to 'never' because property 'reason' has conflicting types in some constituents.(2345)

How can I solve this?

Edit:

Here is the link to the playground:

https://www.typescriptlang.org/play?ts=4.3.5#code/FDDGBsEMGdoAgGIEsBO0AuBhKs4G9g44A3ScAVwFNoAuRVDANTKugBUBPAB0rgF58AXzgx6adMwrVOPANwgi0ShJbUAFKSm0xTVe26UAlHWIB7JABN8hInHQALJNAB0m1v3xxn3t9TiD5IkFgYLAceABlSlBTADsLbBh4AiJfbSiY+MlWGV4BPGFRDLiLbOkDeRslFS0NPTpirL1c4xJzKxTbBydXPQ88Lx8+gJtg0KRY9EoUADNIUF5MUwBbZbiy-R5rWzhLOljyZYAjacDbLhRTHhR0DgBGOgwUCYBzM6ILq+nbgCZH9GesTeIRAlAOyx06AASpQYHEAKLg7a2ACCABo4AAhDGYEHAMGHOCNCwwuGxRGEzpEAAaGIAmhiAFp4iZTWbzXjIcQbXJwSgADym8XgS1W62aBmRKFh0DidC5GFJsvJ4Mq40m0zmCyJ0RKPMlAqFFhFKzWsX1W060rJDV18SVCNVeIgSTgAFkOIlcJ0QDYJkh0GoAPprCyUcDyhhYcJwAA+OsyCXChmRREyGDgofDkfEXvg8eJeY8IdMYfAlR26fQcFilAA7ht+jYdns7mjm+dLtdbg84AByT7d+599s7D5d74cP79weTn4jjtEa3KnOKmWOw7OdEd4JjzOl8POaobNS1ht6QzvfwgQRAA

Your code assumes that model is an instance of FirstClass , but the types say that it could be an instance of FirstClass or it could be an instance of SecondClass . Since it's unclear which it is, but setValues needs to know, TypeScript is highlighting for you that the argument you're passing isn't valid (or perhaps I should say might not be valid). And it can't be valid, because it can't be simultaneously both a FirstValuesType and a SecondValuesType (which is what FirstValuesType & SecondValuesType means), since the types of reason differ.

The minimum-changes way to solve it is to test what you have to see whether it's a FirstClass instance, which you can do since you've used a class (not just an interface). So this fixes it:

if (model instanceof FirstClass) {
    model.setValues(newValues);
} else {
    // ...code here to do something with the `SecondClass` `model`
}

Playground example


That said, you might want to reconsider the overall structure, but it really depends on the specifics and this looks like a simplified example (appropriately simplified, for the purposes of asking the question). FirstClass and SecondClass , and FirstValuesType and SecondValuesType , are identical other than the type of the enum used for reason . You might consider using generic type parameters on a single TheClass and ValuesType instead. But that wouldn't change the fundamental issue that the code in init is assuming that the model is one thing when it may be one or the other of two things.


Side note: This part of the init code seems slightly suspicious:

const model: TheClass<EnumType> = _model;
// ...
model.setValues(newValues);

The model constant and the _model parameter point to the same object , so it would be more direct to not create an unnecessary additional identifier and just use _model directly:

_model.setValues(newValues);

Either way, you're modifying the object that was passed in. (If you meant to copy the object, you'll need to do a copy operation.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM