Static Analysis

A core design consideration in Mountaineer is allowing for full static analysis of your webapps. This term just means that we can verify your code from its text alone without having to run it all. As your webapp grows in scope this becomes increasingly valuable, as it allows you to catch errors early before they become runtime issues. And the more complicated your logic becomes, the more switch conditions and edge cases you're necessarily going to have. Manually testing all that is... not going to be fun.

Since static analysis is a personal choice, we don't yet bundle a type checker within Mountaineer. This page covers some basic suggestions for adding it to your project.

Python

mypy and pyright are the most popular type checkers for Python. They both effectively do the same thing. mypy is a bit more mature and has a larger community, but pyright is often preferred by IDEs so you help ensure your dev workflow is the same as your CI verification. We typically use both in our projects to be extra safe.

poetry add mypy --group dev
poetry add pyright --group dev

Then modify your pyproject.toml to make as strict as you would like. Here's a good starting point for mypy:

[tool.mypy]
warn_return_any = true
warn_unused_configs = true
check_untyped_defs = true
plugins = ["pydantic.mypy"]

Pyright is already a bit stricter by default, but you can really boost the verbosity by specifying:

[tool.pyright]
typeCheckingMode = "strict"

Then, to run against your project:

poetry run mypy
poetry run pyright

Typescript

Typescript's main goal as a language extension to Javascript is to provide typechecking and static analysis. These features are built into the default compiler tsc. As such, most frontend issues in your Mountaineer project are typically caught when we compile your typescript code with poetry run build or progressively with runserver or watch. However there are some cases where you don't want to perform a full build, like in CI where you just want to validate the current state of your project.

npm install typescript --save-dev

The tsconfig.json specifies the level of strictness you want to enforce. These options set to the strictest level will catch the most errors:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  }
}
ParameterDescription
strictEnables all strict type-checking options. Setting this to true is the easiest way to ensure you're using TypeScript's strictest settings.
noImplicitAnyRaises error on expressions and declarations with an implied any type.
strictNullChecksWhen enabled, null and undefined are not in the domain of every type.
strictFunctionTypesEnsures functions' parameters are correctly typed.
strictBindCallApplyEnforce stricter checking of the bind, call, and apply methods on functions.
strictPropertyInitializationEnsures class properties are initialized in the constructor.
noImplicitReturnsReport error when not all code paths in function return a value.
noFallthroughCasesInSwitchPrevent fall-through cases in switch statements.

Then, to run against your project:

{
  "scripts": {
    "typecheck": "tsc --noEmit"
  }
}
npm run typecheck