Skip to content

Commit f8d8310

Browse files
committed
stash
1 parent 0eab0d6 commit f8d8310

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

docs/typescript.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,92 @@ async function removeAccount(address: Hex): Promise<KeyringControllerState> {
3939
return this.fullUpdate();
4040
}
4141
```
42+
43+
## Overriding Types
44+
45+
- Order of preference: `infer` > `:` > `as` > `any`
46+
- Provide explanation via comment when explicitly casting types or overriding related eslint rules (e.g. forbid `any`, forbid `non-null assertions`)
47+
48+
A. Type Inference
49+
50+
- Prefer type inference: Inferences are responsive to changes in code, while assertions rely on brittle hard-coding. While TypeScript will throw type errors against some unsafe or structurally unsound type assertion scenarios, it will generally accept the user-supplied type without type-checking. This can cause silent failures where errors are suppressed.
51+
52+
- Generic Parameters
53+
- `Object.entries`
54+
- `Array.prototype.reduce`
55+
- Type Narrowing
56+
- In some cases, type assertions can be replaced with type narrowing with type guards and null checks.
57+
- Type Guards
58+
- Non-Null Assertions
59+
60+
B. Type Annotations (`:`)
61+
62+
- If a type constraint needs to be imposed, prefer the `satisfies` keyword (for TypeScript v4.9+), since it allows type inference to a more narrow type.
63+
64+
- `:` type declarations also enable type constraints to be imposed, but don't allow narrowing by inference.
65+
66+
C. Type Assertions (`as`)
67+
68+
- `as` assertions intended to exclude an empty/nullable type can be replaced by a nullish coalescing operator converting nullable values into an acceptable empty value that doesn't pollute the variable's type signature.
69+
70+
```ts
71+
(arr as string[])
72+
(arr ?? [])
73+
```
74+
75+
- Acceptable usages of `as`
76+
77+
- To define user-defined type guards: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
78+
- To type inputs/outputs that are defined at runtime, provided that schema validation is performed with type guards and unit tests.
79+
- e.g. The output of `JSON.parse()` or `await response.json()` for a known JSON input.
80+
81+
D. Disable Type Checking (`any`)
82+
83+
- `any` doesn't actually represent the widest type. It's a compiler setting to disable type checking for the value and/or type to which it's assigned.
84+
85+
- If `any` is used, and errors are introduced (or altered) by future changes to the code,
86+
- The new or changed warnings will be suppressed, and the code will **fail silently**.
87+
88+
- `any` infects all surrounding and downstream code.
89+
- For instance, if you have a function that is declared to return any which actually returns an object, all properties of that object will be any.
90+
91+
- `unknown` is the universal supertype i.e. the widest possible type.
92+
- If what's needed is a type that could be "anything," `unknown` should be used.
93+
- When typing the assignee, `any` and `unknown` are interchangeable (every type is assignable to both).
94+
- When typing the assigned, `unknown` is `any` is assignable to all types, while `unknown` is only assignable to `unknown`.
95+
- If replacing `any` with `unknown` doesn't work, the typing likely has underlying issues that *shouldn't be silenced*.
96+
97+
- If no good typing solution can be found, using forced type casting with the `as` keyword or even `as unknown as` is much preferable to using `any`:
98+
- At least we get working intellisense, autocomplete.
99+
- We also get an indication of the expected type as intended by the author.
100+
101+
- Function supertype (assignable to any function):
102+
103+
```ts
104+
(...args: any[]) => any // 🚫
105+
(...args: never[]) => unknown //
106+
```
107+
108+
- Acceptable usages of `any`
109+
110+
- Assigning new properties to an object or class at runtime:
111+
112+
```ts
113+
(this as any)[key] = obj[key]
114+
```
115+
116+
- Within generic constraints:
117+
118+
```ts
119+
messenger extends RestrictedControllerMessenger<N, any, any, string, string>
120+
```
121+
122+
- In general, using `any` in this context is not harmful in the same way that it is in other contexts, as the `any` types are not directly assigned to any specific variable, and only function as constraints.
123+
- That said, narrower constraints provide better type safety and intellisense.
124+
125+
- Catching errors:
126+
- `catch` only accepts `any` and `unknown` as the error type .
127+
- Recommended: Use `unknown` with type guards like `isJsonRpcError` .
128+
129+
- In tests, for mocking or to intentionally break features.
130+
- Recommended: Provide accurate typing through assertions wherever possible.

0 commit comments

Comments
 (0)