TypeScript
Create and pass a logicType
β
To add TypeScript support to your logic, create a logicType
, and pass it as the kea
function's type argument:
import { kea, actions, reducers } from 'kea'
import { loginLogicType } from './loginLogicType'
const loginLogic = kea<loginLogicType>([
actions({
setUsername: (username: string) => ({ username }),
}),
reducers({
username: ['keajs', { setUsername: (_, { username }) => username }],
// ...
}),
])
This provides automatic typing wherever you use the logic:
Option 1: MakeLogicType<V, A, P>
β
There are two ways you can get a logicType
. The first is manually:
interface Values {
id: number
created_at: string
name: string
pinned: boolean
}
interface Actions {
setName: (name: string) => { name: string }
}
interface Props {
id: number
}
type myLogicType = MakeLogicType<Values, Actions, Props>
const myLogic = kea<myLogicType>([
actions({
setName: (name) => ({ name }),
}),
reducers({
name: ['', { setName: (_, { name }) => name }],
// etc
}),
])
Option 2: kea-typegen
β
The second way is with kea-typegen
, which uses the TypeScript Compiler API to analyse your .ts
files and generate type definitions for your logic.
Run kea-typegen write
or kea-typegen watch
and get a bunch of logicType.ts
files:
The generated types will be automatically added to the kea()
call.
import { kea } from 'kea'
import { githubLogicType } from './githubLogicType'
export const githubLogic = kea<githubLogicType>([
// ^^^^^^^^^^^^^^^^^ π added automatically
actions({ skip }),
reducers({ skip }),
listeners(({ actions }) => ({ skip })),
])
It's a bit of extra work, but works like magic once set up!
Installationβ
First install the kea-typegen
and typescript
packages:
# if you're using yarn
yarn add --dev kea-typegen typescript
# if you're using npm
npm install kea-typegen typescript --save-dev
Running typegenβ
- While developing, run
kea-typegen watch
, and it'll generate new types every time your logic changes. - Run
kea-typegen write
to generate all the types, for example before a production build. - Finally,
kea-typegen check
can be used to see if any types need to be written
Here's a sample pacakge.json
, that uses concurrently
to run kea-typegen watch
together with webpack while developing:
# if you're using yarn
yarn add --dev concurrently
# if you're using npm
npm install concurrently --save-dev
{
"scripts": {
"start": "concurrently \"yarn start:app\" \"yarn start:kea\" -n APP,KEA -c blue,green",
"start:app": "webpack-dev-server",
"start:kea": "kea-typegen watch --write-paths"
}
}
When should you specify types?β
With TypeGen, you should only need to specify each type once. This means at the boundaries: the action
parameters and
any defaults
, including in reducers
or loaders
. Everything else, including various return types, should be detected
automatically.
import { Blog } from './blog'
import { logicType } from './logicType'
export const LocalType = 'YES' | 'NO'
// The kea<...> part is automatically added and kept up to date by kea-typegen
const logic = kea<logicType<LocalType>>([
actions({
openBlog: (id: number, blog?: Blog) => ({ id, blog }), // π add types here
closeBlog: (answer: LocalType) => ({ answer }),
}),
reducers({
blogId: [
null as number | null, // π null now, but sometimes a number π
{ openBlog: (_, { id }) => id, closeBlog: () => null },
],
}),
listeners({
closeBlog: ({ answer }) => {
console.log(answer)
},
}),
])
Files generated with kea-typegen will automatically import any types they can, and add the rest as type arguments
for kea<logicType<LocalType, LocalUser>>
Create logic-builder-type-buildersβ
If you're building custom logic builders, and want typegen to automatically generate types, you must write a logic-builder-type-builder. π
This involves creating a typegen.ts
or a setters.typegen.ts
file next to your setters.ts
builder. This file should
export a function with the same name as the builder, and similar to the builder, add various actions, reducers
and other features on the type of the logic.
Check out the sample typedForm.typegen.ts,
or the more full-featured typegen.ts
from kea-forms,
for examples of such type builders.
note
These type builders area a new area of development for kea, starting with 3.0, and we're working on making this API simpler for all.
For now, you'll need to know how the TypeScript Compiler API works, and write code to manipulate TypeScript Node
s and TypeNode
s.
ProTip: Get a useful debugger, and use the TypeScript AST Viewer.
Caveats / Known issuesβ
- Using namespaced types like
ExportedApi.RandomThing
is slightly broken. You may sometimes need to create aninterface
thatextends
the original type, and use that in your actions/reducers. Creating atype
alias will not work, as "One difference is that interfaces create a new name that is used everywhere. Type aliases donβt create a new name β for instance, error messages wonβt use the alias name". For example:
interface RandomThing extends ExportedApi.RandomThing {}
Alternatively, disable such errors in your
logicType.tsx
files, by passing--add-ts-nocheck
to kea-typegen.With some tools you might need to "Reload All Files" or explicitly open
logicType.ts
to see the changes.Adding types with
logic.extend()
isn't implemented yet.
Found a bug? Some type wrongly detected? Post an issue in the kea-typegen repository.
Questions & Answers
Ask questions about this page here.