with one click
typescript
TypeScript-specific conventions including ts-expect-error usage, unknown vs any, const assertions, and type vs interface preferences. Use when writing TypeScript code.
Menu
TypeScript-specific conventions including ts-expect-error usage, unknown vs any, const assertions, and type vs interface preferences. Use when writing TypeScript code.
publishConfig rules for public npm packages in the Trezor Suite monorepo. Use when adding or editing publishConfig, exports, or preparing a package for npm publishing.
How to create and structure packages in the Trezor Suite monorepo, including scopes and sizing guidance. Use when creating new packages or resolving cyclic dependencies.
Use when writing component or hook tests in suite-native and need to choose between renderWithBasicProvider, renderWithStoreProvider, or store helpers like createStoreFromPreloadedState, createLightStore, or mergePreloadedState.
Generated code must be aligned with security headers (e.g. no unsave JS eval). The permissions policy is especially relevant when changing any code related with the `navigator` object.
Trigger on any mention of Trezor wallet interaction, crypto addresses, sending crypto, checking balances, signing messages, or hardware wallet operations via MCP. Also trigger when users mention configuring or troubleshooting the Trezor MCP server connection.
How to create and implement IndexedDB storage migrations in the Trezor Suite web app. Use when writing migrations that transform persisted data between Suite versions.
| name | typescript |
| description | TypeScript-specific conventions including ts-expect-error usage, unknown vs any, const assertions, and type vs interface preferences. Use when writing TypeScript code. |
@ts-expect-error to @ts-ignoreTypeScript allows you to suppress all errors on a line by placing a single-line comment or a comment block line starting with @ts-ignore immediately before the erroring line. While powerful, there is no way to know if a @ts-ignore is actually suppressing an error without manually investigating what happens when the @ts-ignore is removed.
This means it's easy for @ts-ignores to be forgotten about and remain in code even after the error they were suppressing is fixed. This is dangerous, as if a new error arises on that line, it'll be suppressed by the forgotten about @ts-ignore, and so be missed.
To address this, TS3.9 ships with a new single-line comment directive: // @ts-expect-error.
This directive operates in the same manner as @ts-ignore, but will error if the line it's meant to be suppressing doesn't actually contain an error, making it a lot safer.
š” Sometimes in very rare cases you may still need
@ts-ignore. In that case you need to disable ESLint for that line first; otherwise, ESLint will automatically change it to@ts-expect-error.
unknown to anyUse unknown for situations where a function doesn't know the incoming type and not when it doesn't care about the type. With better type safety, unknown can help us catch possible errors early on.
š¢ Type guard using unknown:
const validateKey = (key: unknown): key is DictionaryKey => {
if (['string', 'number'].includes(typeof key)) {
return true;
}
return false;
};
If the above type guard marked key as any, calling key() would not throw.
Prefer directly importing types used in a file rather than accessing them indirectly.
š“ Indirect assignment:
const doSomething = (networkSymbol: Account['symbol']) => {};
š¢ Direct assignment:
import { NetworkSymbol } from '@suite-common/wallet-config';
const doSomething = (networkSymbol: NetworkSymbol) => {};
Direct assignment may add an import, but it prevents the need to refactor if the NetworkSymbol detaches from Account, is easier to read and makes it easier to navigate to the NetworkSymbol type definition in the editor.
See https://www.youtube.com/watch?v=0fTdCSH_QEU. TypeScript enums are not native to JavaScript and sometimes behave unpredictably. The desired functionality can be achieved using plain objects. Follow the same naming conventions as you would with enums. Despite the object and the type having the same name, TypeScript is able to tell them apart.
// definition
const AuthMethod = {
Push: 'Push',
Sms: 'SMS',
} as const;
type AuthMethod = (typeof AuthMethod)[keyof typeof AuthMethod];
// usage
function doThing(authMethod: AuthMethod): void {
console.log(authMethod);
}
doThing(AuthMethod.Sms);
doThing('SMS');
Just to be consistent. Interfaces offer advanced functionality we don't really use. Related video: https://www.youtube.com/watch?v=zM9UPcIyyhQ