Skip to content

Commit 24ff483

Browse files
authored
chore: clarify more breaking changes (#4962)
This comes up a lot. Describe how b/w compat works. --- By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license]. [Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
2 parents e80ca4d + 4588ddc commit 24ff483

File tree

1 file changed

+27
-1
lines changed

1 file changed

+27
-1
lines changed

packages/jsii-diff/BREAKING_CHANGES.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ const d = new Dog({ name: 'Fido' });
4949
console.log(d.name.toLowerCase());
5050

5151
// Not valid anymore after the type of `d.name` has changed into `string | undefined`.
52-
// 'd.name' can be undefined, and we have to account for that with an `if`!
52+
// 'd.name' can be undefined, and calling `undefined.toLowerCase()` would throw an error.
53+
// The user will have to account for that with an `if`, which means changing their code,
54+
// which means a breaking change.
5355
```
5456

5557
### Optional properties: how to solve
@@ -83,6 +85,30 @@ This doesn't break any existing users: all their Dogs will have names, so they w
8385

8486
For new users that fail to give their Dog a name, presumably they will be aware that their Dog doesn't have a name, so they can avoid trying to read it. If you want to give them a way to avoid the exception, add a `public get hasName(): boolean` field so they can test for the existence of the name before accessing it.
8587

88+
### Optional properties: what about structs?
89+
90+
In the above example, we said that `DogOptions#name` was an *input* and `Dog#name` was an *output*. Does that mean it's
91+
always okay to change struct (data interface) fields to optional?
92+
93+
Not necessarily! It depends on how the struct is used. If the struct is used as the return value of a method or the
94+
type of a class proeprty somewhere, it is in *output position* and all of its fields are as well. So if you have the following
95+
class:
96+
97+
```ts
98+
class Dog {
99+
public readonly options: DogOptions; // DogOptions is an OUTPUT
100+
101+
constructor(options: DogOptions) { // DogOptions is an INPUT
102+
this.options = options;
103+
}
104+
}
105+
```
106+
107+
Then `DogOptions` is now both in input as well as output position, and you're not allowed to make anything optional anymore!
108+
109+
(That's why using the same struct name to represent both input and output data is best avoided, because it limits
110+
evolvability).
111+
86112
## Changing types to superclass/subclass
87113

88114
When changing types involved in an operation, you run into a similar issue as with changing the optionality of a property:

0 commit comments

Comments
 (0)