-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9950b74
commit b0e7ef8
Showing
1 changed file
with
77 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,94 @@ | ||
# TypeScript Conventions | ||
|
||
## Use interfaces & functions, not classes | ||
|
||
Use exclusively interfaces & standalone functions internally. This keeps code | ||
clean, legible, and easy to refactor at the cost of slightly more verbosity. | ||
|
||
Examples: `Project`, `Registry`, `Module`, `Script` | ||
|
||
## Only use classes for developer-facing APIs | ||
|
||
We don't expect the user to use pure interfaces & functions; consuming well | ||
designed OOP interfaces can be cleaner. | ||
|
||
Examples of using classes: `Context` and `Runtime` are classes designed to have | ||
a clean interface for the user. | ||
|
||
Examples of using interfaces: `Trace` is a simple data container that can be | ||
easily serialized & deserialized. There are standalone functions that can | ||
operate on a trace. | ||
|
||
## Camel case + acryonyms | ||
|
||
OpenApi vs OpenAPI Uuid vs UUID | ||
Follow camel case strictly & treat acronyms as single words. | ||
|
||
Examples: | ||
|
||
TODO | ||
- Prefer `OpenApi` insetad of `OpenAPI` | ||
- Prefer `Uuid` instead of `UUID` | ||
|
||
## Uses of `id` included with type | ||
|
||
`id` vs `userId` | ||
When referring to the ID of the current type, use `id`. When referring to a | ||
foreign type, use `{type name}Id`. | ||
|
||
Example: | ||
|
||
```prisma | ||
model User { | ||
id String @id @default(uuid()) @db.Uuid | ||
posts Post[] | ||
} | ||
TODO | ||
model Post { | ||
id String @id @default(uuid()) @db.Uuid | ||
userId String @db.Uuid | ||
user User @relation(fields: [userId], references: [id]) | ||
} | ||
``` | ||
|
||
## Externally tagged enums | ||
|
||
Easy to represent in OpenAPI & external languages compared to internally tagged | ||
enums | ||
When representing an enum with associated data (often called "sum types" which are a kind of algebreic data type, ADT), represent using a nested object (often called "externally tagged enums"). | ||
|
||
This comes at the expense of not having exhaustive switch statements. | ||
|
||
Externally tagged enums are easy to represent in languages that don't support advanced type constraints, such as C# and most OpenAPI SDK generators (i.e. don't support `oneOf`). | ||
|
||
This example: | ||
|
||
```typescript | ||
type MyEnum = { foo: MyEnumFoo } | { bar: MyEnumBar } | { baz: MyEnumBaz }; | ||
|
||
interface MyEnumFoo { | ||
|
||
} | ||
|
||
interface MyEnumBar { | ||
|
||
} | ||
|
||
interface MyEnumBaz { | ||
|
||
} | ||
``` | ||
|
||
Comes at the down side of not having exhaustive switch statements | ||
Can be represented in C# like this: | ||
|
||
## Avoid OOP at all costs | ||
```cs | ||
class MyEnum { | ||
MyEnumFoo? Foo; | ||
MyEnumBar? Bar; | ||
MyEnumBaz? Baz; | ||
} | ||
|
||
## Prefer interfaces for rich data, prefer classes for functional objects | ||
class MyEnumFoo { | ||
} | ||
|
||
`Trace` simply stores data. Helper functions can be published to manage traces. | ||
class MyEnumBar { | ||
} | ||
|
||
`Context` and `Runtime` are functional classes that have associated methods & | ||
constructors. | ||
class MyEnumBaz { | ||
} | ||
``` |