Skip to content

Commit cf4a0b6

Browse files
authored
feat: support class covariant overrides in kernel, tools and docs (#4925)
Updates docs and additional tools with support for class covariant overrides. --- 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
1 parent 254043f commit cf4a0b6

File tree

30 files changed

+2235
-63
lines changed

30 files changed

+2235
-63
lines changed

gh-pages/content/user-guides/lib-author/typescript-restrictions.md

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ coexist in the same closure, it is recommended to also declare all such dependen
1818

1919
Occasionally, a dependency on a *non-jsii module* is useful. Since such dependencies do not have generated bindings in
2020
all the supported languages, they must be bundled with the *jsii module* that depends on them, by adding the library
21-
into the `bundleDependencies` array in `package.json`.
21+
into the `bundleDependencies` array in `package.json`.
2222

2323
The API of the *jsii module* can not expose any type from bundled dependencies, since those types would not be available in other languages.
2424
TypeScript files that include a non-jsii dependency (e.g. a lambda handler for an AWS CDK Construct) cannot be exported from the `main`/`types` entry point.
@@ -137,40 +137,53 @@ export class Subclass extends Base {
137137
### Covariant Overrides & Parameter List Changes
138138

139139
In **TypeScript**, overriding members can have a signature that differs from the overridden member as long as the new
140-
signature is compatible with the parent. This is however not supported as:
140+
signature is compatible with the parent. This is only partially supported in jsii as:
141141

142-
- **Java** and **C#** do not support omitting parameters when overriding or implementing a member
143-
- **C#** does not support overriding or implementing a member using covariant parameter or return types
142+
- In **C#** when implementing interfaces, you cannot override members or change return types
143+
- **C#** only supports covariant overrides to `readonly` properties
144+
- Both **Java** and **C#** do not support omitting parameters when overriding or implementing a method
145+
- In **C#** you cannot override method parameters
144146

145-
!!! note
146-
**C# 9** introduces support for covariant return types, which would allow relaxing this restriction, however `jsii`
147-
must build code targetting the `.NET Core 3.1` runtime, which only supports **C# 8**. Once `.NET Core 3.1` becomes
148-
end-of-life, this may change.
147+
As a consequence, changes to member signatures are only allowed in very few cases.
148+
All overrides must be covariant to the parent type.
149+
150+
- Return type of (non-static) methods
151+
- `readonly` properties
152+
153+
```ts hl_lines="10-11 13-14 16-17 19-20 22-23"
154+
export class SuperClass {}
155+
export class SubClass extends SuperClass {}
149156

150-
```ts hl_lines="6-7 9-10 12-13"
151157
export class Base {
152-
public method(param: any): any { /* ... */ }
158+
public readonly prop: SuperClass;
159+
public method(param: SuperClass): SuperClass { /* ... */ }
153160
}
154161

155162
export class Child extends Base {
156163
// 💥 Parameter signatures do not match
157164
public method(): any { /* ... */ }
158165

159166
// 💥 Parameter types do not match, even though they are covariant
160-
public method(param: string): any { /* ... */ }
167+
public method(param: SubClass): any { /* ... */ }
168+
169+
// 💥 Property types do not match
170+
public readonly prop: string;
171+
172+
// ✅ Return type is covariant
173+
public method(param: SuperClass): SubClass { /* ... */ }
161174

162-
// 💥 Return type does not match, even though it is covariant
163-
public method(param: any): string { /* ... */ }
175+
// ✅ Property is readonly and override type is covariant
176+
public readonly prop: SubClass;
164177
}
165178
```
166179

167180
## Index Signatures
168181

169-
**TypeScript** allows declaring _additional properties_ through the use of index signatures. These are however not
170-
supported by the _jsii type system_ and are rejected by the compiler.
182+
**TypeScript** allows declaring *additional properties* through the use of index signatures. These are however not
183+
supported by the *jsii type system* and are rejected by the compiler.
171184

172185
!!! info
173-
Version `1.x` of the compiler _silently ignores_ index signatures instead of reporting a compilation error. Users
186+
Version `1.x` of the compiler *silently ignores* index signatures instead of reporting a compilation error. Users
174187
with offending APIs migrating from `jsii@1.x` to `jsii@5.0` or newer need to either remove those declarations, or
175188
explicitly ignore them using the [`@jsii ignore` tag](./hints.md#excluding-a-declaration-from-multi-language-support).
176189

packages/@jsii/kernel/src/kernel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as tar from './tar-cache';
1414

1515
export const ASSEMBLY_SUPPORTED_FEATURES: spec.JsiiFeature[] = [
1616
'intersection-types',
17+
'class-covariant-overrides',
1718
];
1819

1920
export const enum JsiiErrorType {

packages/@scope/jsii-calc-base-of-base/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
"test:update": "yarn build && UPDATE_DIFF=1 yarn test"
3131
},
3232
"devDependencies": {
33-
"jsii": "5.9.6",
33+
"jsii": "5.9.10" ,
3434
"jsii-build-tools": "^0.0.0",
35-
"jsii-rosetta": "^5.9.6"
35+
"jsii-rosetta": "^5.9.10"
3636
},
3737
"jsii": {
3838
"outdir": "dist",

packages/@scope/jsii-calc-base-of-base/test/assembly.jsii

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"description": "An example transitive dependency for jsii-calc.",
1111
"homepage": "https://github.com/aws/jsii",
12-
"jsiiVersion": "5.9.6",
12+
"jsiiVersion": "5.9.10",
1313
"license": "Apache-2.0",
1414
"metadata": {
1515
"jsii": {
@@ -169,5 +169,5 @@
169169
}
170170
},
171171
"version": "2.1.1",
172-
"fingerprint": "xT3ki285s4Oa3XH7pWYl1ZcUwKM/TNBnRDafyUmYtHI="
172+
"fingerprint": "AbBUV89p1JNPINTe/piccMNNl5747p+idp5yBUhPLDs="
173173
}

packages/@scope/jsii-calc-base/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@
3535
"@scope/jsii-calc-base-of-base": "^2.1.1"
3636
},
3737
"devDependencies": {
38-
"jsii": "5.9.6",
38+
"jsii": "5.9.10" ,
3939
"jsii-build-tools": "^0.0.0",
40-
"jsii-rosetta": "^5.9.6"
40+
"jsii-rosetta": "^5.9.10"
4141
},
4242
"jsii": {
4343
"metadata": {

packages/@scope/jsii-calc-base/test/assembly.jsii

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
},
4040
"description": "An example direct dependency for jsii-calc.",
4141
"homepage": "https://github.com/aws/jsii",
42-
"jsiiVersion": "5.9.6",
42+
"jsiiVersion": "5.9.10",
4343
"license": "Apache-2.0",
4444
"metadata": {
4545
"jsii": {
@@ -210,5 +210,5 @@
210210
}
211211
},
212212
"version": "0.0.0",
213-
"fingerprint": "uC/anzvNeUVZQRLakfLl74E6VUDzG7IrE8IlleLhl0E="
213+
"fingerprint": "HHXEe85+CLPcZkhBH2jorRzc70ystyidBOchIn4e5ZY="
214214
}

packages/@scope/jsii-calc-lib/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@
3939
"@scope/jsii-calc-base-of-base": "^2.1.1"
4040
},
4141
"devDependencies": {
42-
"jsii": "5.9.6",
42+
"jsii": "5.9.10" ,
4343
"jsii-build-tools": "^0.0.0",
44-
"jsii-rosetta": "^5.9.6"
44+
"jsii-rosetta": "^5.9.10"
4545
},
4646
"jsii": {
4747
"outdir": "dist",

packages/@scope/jsii-calc-lib/test/assembly.jsii

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"stability": "deprecated"
7272
},
7373
"homepage": "https://github.com/aws/jsii",
74-
"jsiiVersion": "5.9.6",
74+
"jsiiVersion": "5.9.10",
7575
"license": "Apache-2.0",
7676
"metadata": {
7777
"jsii": {
@@ -1164,5 +1164,5 @@
11641164
}
11651165
},
11661166
"version": "0.0.0",
1167-
"fingerprint": "8chnxF4yP6o6nmn+pwW/moRmLso8MgyFcPoNyGJhA+Y="
1167+
"fingerprint": "YiI6GOYJnt4wjMhkzNuI09K72cTolvyrLVauNPkW6nI="
11681168
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* This module demonstrates covariant overrides support in jsii.
3+
*
4+
* Covariant overrides allow derived classes to override methods with more specific return types.
5+
* This was previously not supported because C# didn't allow it, but newer versions of C# (9.0+) do.
6+
*/
7+
8+
/** Base class in the inheritance hierarchy */
9+
export class Superclass {}
10+
11+
/** Derived class that extends Superclass */
12+
export class Subclass extends Superclass {}
13+
14+
/** Further derived class that extends Subclass */
15+
export class SubSubclass extends Subclass {}
16+
17+
export interface IBase {
18+
readonly something: Superclass;
19+
}
20+
21+
/** Base class with methods and properties that will be overridden with covariant return types */
22+
export class Base implements IBase {
23+
public readonly something: Superclass = new Superclass();
24+
public readonly list: Superclass[] = new Array<Superclass>();
25+
26+
public createSomething(): Superclass {
27+
return new Superclass();
28+
}
29+
}
30+
31+
/** Middle class in the inheritance chain - doesn't override anything */
32+
export class Middle extends Base {
33+
public addUnrelatedMember = 3;
34+
}
35+
36+
/**
37+
* Derived class that demonstrates covariant overrides.
38+
*
39+
* Both property and method overrides are covariant and will work in C# 9.0+
40+
* when the covariant-overrides feature is enabled.
41+
*/
42+
export class Derived extends Middle {
43+
// This property override is covariant (SubSubclass extends Superclass)
44+
public readonly something: SubSubclass = new SubSubclass();
45+
public readonly list: Superclass[] = new Array<SubSubclass>();
46+
47+
// This method override is covariant and will work in C# 9.0+
48+
public createSomething(): SubSubclass {
49+
return new SubSubclass();
50+
}
51+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * as classOverrides from './class-overrides';

0 commit comments

Comments
 (0)