From 23681c6fad00897f57029aa5e33ba017b501e333 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 15:49:31 -0700 Subject: [PATCH 01/10] docs: add typescript guide --- guides/index.md | 1 + guides/typescript/index.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 guides/typescript/index.md diff --git a/guides/index.md b/guides/index.md index 0a7f07f0a53..090d25acb13 100644 --- a/guides/index.md +++ b/guides/index.md @@ -2,5 +2,6 @@ - [Relationships](./relationships/index.md) - [Requests](./requests/index.md) +- [Typescript](./typescript/index.md) - [Terminology](./terminology.md) - [Cookbook](./cookbook/index.md) diff --git a/guides/typescript/index.md b/guides/typescript/index.md new file mode 100644 index 00000000000..2074976f1f7 --- /dev/null +++ b/guides/typescript/index.md @@ -0,0 +1,31 @@ +# 💚 TypeScript Guide + +We publish types in stages, a bit like canary vs beta vs stable channels for code. + +- `private` we don't ship types (yet) +- `alpha` we expect high churn on type signatures and users must opt-in to use these types. +- `beta` we expect moderate churn on type signatures and users must opt-in to use these types. +- `stable` we feel the types story is robust enough to attempt to follow semver when changing these types. + +Each package in the project can choose its own stage for types. + +TypeScript support for all EmberData and WarpDrive packages is currently `alpha`. **This means that you must opt-in to be able use EmberData's types.** + +--- + +## Installation + +There are currently two ways to gain access to EmberData's native types. + +1) Use Canary (latest canary is ![NPM Canary Version](https://img.shields.io/npm/v/ember-data/canary?label=%40canary&color=FFBF00)) + +2) Use the `@ember-data-types/*` and `@warp-drive-types/*` packages +with releases `>= 4.12.*` + + +> [!CAUTION] +> EmberData does not maintain the DefinitelyTyped types for +> EmberData (e.g. the `@types/ember-data__*`). If you were +> previously using these, you should uninstall them first. + + From b999dbbb6b4273844772feb0fdacdc83d735e697 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 15:52:53 -0700 Subject: [PATCH 02/10] updates --- guides/typescript/index.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/guides/typescript/index.md b/guides/typescript/index.md index 2074976f1f7..9a81c9bcf16 100644 --- a/guides/typescript/index.md +++ b/guides/typescript/index.md @@ -1,15 +1,20 @@ # 💚 TypeScript Guide -We publish types in stages, a bit like canary vs beta vs stable channels for code. +## Type Maturity -- `private` we don't ship types (yet) +We publish types in stages, just like `canary | beta | stable` channels for code. + +- `private` we don't ship types (yet), even if typed in the repo - `alpha` we expect high churn on type signatures and users must opt-in to use these types. - `beta` we expect moderate churn on type signatures and users must opt-in to use these types. - `stable` we feel the types story is robust enough to attempt to follow semver when changing these types. Each package in the project can choose its own stage for types. -TypeScript support for all EmberData and WarpDrive packages is currently `alpha`. **This means that you must opt-in to be able use EmberData's types.** +> [!TIP] +> TypeScript support for all EmberData and WarpDrive packages is currently `alpha`. +> +> **This means that you must opt-in to be able use EmberData's types.** --- From db5f5d03e2d0cab6d6b7e0a6646143e68acef03b Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 16:27:01 -0700 Subject: [PATCH 03/10] restructure and add more notices --- guides/typescript/0-installation.md | 48 ++++++++++++++++++++++++++++ guides/typescript/1-configuration.md | 22 +++++++++++++ guides/typescript/index.md | 44 +++++++++++++++++-------- 3 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 guides/typescript/0-installation.md create mode 100644 guides/typescript/1-configuration.md diff --git a/guides/typescript/0-installation.md b/guides/typescript/0-installation.md new file mode 100644 index 00000000000..17033c3afec --- /dev/null +++ b/guides/typescript/0-installation.md @@ -0,0 +1,48 @@ +# Installation + +There are currently two ways to gain access to EmberData's native types. + +1) [Use Canary](#using-canary) (latest canary is ![NPM Canary Version](https://img.shields.io/npm/v/ember-data/canary?label=%40canary&color=FFBF00)) + +2) [Use Official Types Packages](#using-types-packages) +with releases `>= 4.12.*` + + +> [!CAUTION] +> EmberData does not maintain the DefinitelyTyped types for +> EmberData (e.g. the `@types/ember-data__*`). If you were +> previously using these, you should uninstall them first. + +### Using Canary + +> [!IMPORTANT] +> Type definitions need to be installed top-level, this means +> you have to install every EmberData package `ember-data` +> depends on. + +Required Packages for Canary Types + +| Name | Version | +| ---- | ------- | +| [ember-data](https://github.com/emberjs/data/blob/main/packages/-ember-data/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/ember-data/canary?label=&color=90EE90) | +| [@ember-data/adapter](https://github.com/emberjs/data/blob/main/packages/adapter/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/adapter/canary?label=&color=90EE90) | +| [@ember-data/graph](https://github.com/emberjs/data/blob/main/packages/graph/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/graph/canary?label=&color=90EE90) | +| [@ember-data/json-api](https://github.com/emberjs/data/blob/main/packages/json-api/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/json-api/canary?label=&color=90EE90) | +| [@ember-data/legacy-compat](https://github.com/emberjs/data/blob/main/packages/legacy-compat/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/legacy-compat/canary?label=&color=90EE90) | +| [@ember-data/model](https://github.com/emberjs/data/blob/main/packages/model/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/model/canary?label=&color=90EE90) | +| [@ember-data/request](https://github.com/emberjs/data/blob/main/packages/request/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/request/canary?label=&color=90EE90) | +| [@ember-data/request-utils](https://github.com/emberjs/data/blob/main/packages/request-utils/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/request-utils/canary?label=&color=90EE90) | +| [@ember-data/serializer](https://github.com/emberjs/data/blob/main/packages/serializer/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/serializer/canary?label=&color=90EE90) | +| [@ember-data/store](https://github.com/emberjs/data/blob/main/packages/store/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/store/canary?label=&color=90EE90) | +| [@ember-data/tracking](https://github.com/emberjs/data/blob/main/packages/tracking/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/tracking/canary?label=&color=90EE90) | +| [@warp-drive/core-types](https://github.com/emberjs/data/blob/main/packages/core-types/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40warp-drive/core-types/canary?label=&color=90EE90) | + + +### Using Types Packages + +> [!IMPORTANT] +> Type definitions need to be installed top-level, this means +> you have to install types for every EmberData package +> `ember-data` depends on. + +the `@ember-data-types/*` and `@warp-drive-types/*` packages diff --git a/guides/typescript/1-configuration.md b/guides/typescript/1-configuration.md new file mode 100644 index 00000000000..aa5fa96d928 --- /dev/null +++ b/guides/typescript/1-configuration.md @@ -0,0 +1,22 @@ +# Configuration + +There are currently two ways to gain access to EmberData's native types. +Follow the configuration guide below for the [installation](./0-installation.md) +option you chose. + +1) [Use Canary](#using-canary) + +2) [Use Official Types Packages](#using-types-packages) +with releases `>= 4.12.*` + + +> [!CAUTION] +> EmberData does not maintain the DefinitelyTyped types for +> EmberData (e.g. the `@types/ember-data__*`). If you were +> previously using these, you should uninstall them first. + +### Using Canary + + + +### Using Types Packages diff --git a/guides/typescript/index.md b/guides/typescript/index.md index 9a81c9bcf16..1b531263671 100644 --- a/guides/typescript/index.md +++ b/guides/typescript/index.md @@ -1,5 +1,30 @@ # 💚 TypeScript Guide +Before getting started, we recommend reading +the following two sections + +- [Notice on Type Maturity](#type-maturity) +- [Contributing Type Fixes](#contributing-type-fixes) + + +--- + +- Installation + - [Using Canary](./0-installation.md#using-canary) + - [Using Types Packages](./0-installation.md#using-types-packages) +- Configuration + - [Using Canary](./1-configuration.md#using-canary) + - [Using Types Packages](./1-configuration.md#using-types-packages) +- Usage + - Typing Models + - Typing Transforms + - Typing Requests + - Typing Builders + - Typing Handlers + - Using Store APIs + +--- + ## Type Maturity We publish types in stages, just like `canary | beta | stable` channels for code. @@ -16,21 +41,12 @@ Each package in the project can choose its own stage for types. > > **This means that you must opt-in to be able use EmberData's types.** ---- - -## Installation - -There are currently two ways to gain access to EmberData's native types. - -1) Use Canary (latest canary is ![NPM Canary Version](https://img.shields.io/npm/v/ember-data/canary?label=%40canary&color=FFBF00)) - -2) Use the `@ember-data-types/*` and `@warp-drive-types/*` packages -with releases `>= 4.12.*` +## Contributing Type Fixes +Even though EmberData is typed, what makes for good types for a project doesn't necessarily make for good types for that project's consumers (your application). -> [!CAUTION] -> EmberData does not maintain the DefinitelyTyped types for -> EmberData (e.g. the `@types/ember-data__*`). If you were -> previously using these, you should uninstall them first. +Currently, TypeScript support is `alpha` largely because we expect to need to improve **a lot** of type signatures to make them more useful and correct for your app. +Both strategies for installing and consuming types listed in [installation](./0-installation.md) pull their types from the `main` branch (canary). +Every commit to main can be one-click published by us as a new canary version for both installation strategies, this means we can ship type fixes as quickly as folks contribute them, letting us dogfood our way to robust stable types. From 5e30da5813723299276504859de113d7a9c52b13 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 16:52:48 -0700 Subject: [PATCH 04/10] finish install instructions --- guides/typescript/0-installation.md | 127 +++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) diff --git a/guides/typescript/0-installation.md b/guides/typescript/0-installation.md index 17033c3afec..560e4307713 100644 --- a/guides/typescript/0-installation.md +++ b/guides/typescript/0-installation.md @@ -1,8 +1,12 @@ # Installation +> [!TIP] +> EmberData's Native Types require the use of Ember's +> Native Types. + There are currently two ways to gain access to EmberData's native types. -1) [Use Canary](#using-canary) (latest canary is ![NPM Canary Version](https://img.shields.io/npm/v/ember-data/canary?label=%40canary&color=FFBF00)) +1) [Use Canary](#using-canary) 2) [Use Official Types Packages](#using-types-packages) with releases `>= 4.12.*` @@ -37,6 +41,56 @@ Required Packages for Canary Types | [@ember-data/tracking](https://github.com/emberjs/data/blob/main/packages/tracking/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/tracking/canary?label=&color=90EE90) | | [@warp-drive/core-types](https://github.com/emberjs/data/blob/main/packages/core-types/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40warp-drive/core-types/canary?label=&color=90EE90) | +Here's an example change to package.json which drops all use of types from `@types/` for both Ember and EmberData and adds the appropriate canary packages. + +```diff +- "@types/ember": "4.0.11", +- "@types/ember-data": "4.4.16", +- "@types/ember-data__adapter": "4.0.6", +- "@types/ember-data__model": "4.0.5", +- "@types/ember-data__serializer": "4.0.6", +- "@types/ember-data__store": "4.0.7", +- "@types/ember__application": "4.0.11", +- "@types/ember__array": "4.0.10", +- "@types/ember__component": "4.0.22", +- "@types/ember__controller": "4.0.12", +- "@types/ember__debug": "4.0.8", +- "@types/ember__destroyable": "4.0.5", +- "@types/ember__engine": "4.0.11", +- "@types/ember__error": "4.0.6", +- "@types/ember__helper": "4.0.7", +- "@types/ember__modifier": "4.0.9", +- "@types/ember__object": "4.0.12", +- "@types/ember__owner": "4.0.9", +- "@types/ember__routing": "4.0.22", +- "@types/ember__runloop": "4.0.10", +- "@types/ember__service": "4.0.9", +- "@types/ember__string": "3.16.3", +- "@types/ember__template": "4.0.7", +- "@types/ember__test": "4.0.6", +- "@types/ember__utils": "4.0.7", +- "ember-data": "~5.3.3", ++ "ember-data": "5.4.0-alpha.52", ++ "@ember-data/store": "5.4.0-alpha.52", ++ "@ember-data/adapter": "5.4.0-alpha.52", ++ "@ember-data/graph": "5.4.0-alpha.52", ++ "@ember-data/json-api": "5.4.0-alpha.52", ++ "@ember-data/legacy-compat": "5.4.0-alpha.52", ++ "@ember-data/request": "5.4.0-alpha.52", ++ "@ember-data/request-utils": "5.4.0-alpha.52", ++ "@ember-data/serializer": "5.4.0-alpha.52", ++ "@ember-data/model": "5.4.0-alpha.52", ++ "@ember-data/tracking": "5.4.0-alpha.52", ++ "@warp-drive/core-types": "0.0.0-alpha.38", +``` + +> [!TIP] +> If your package manager enables deduping, we recommend deduping types as much as possible. + +>[!TIP] +> It is best to ensure no other dependencies are still bringing `@types/*` packages as this will cause weird type bugs. + +--- ### Using Types Packages @@ -45,4 +99,73 @@ Required Packages for Canary Types > you have to install types for every EmberData package > `ember-data` depends on. -the `@ember-data-types/*` and `@warp-drive-types/*` packages +Every package in the project that ships types also publishes its types under a second package name. +This enables older releases to consume these types instead of relying on the DefinitelyTyped project. + +These types-only packages have the same version number as the version they were published with, and their org or name is suffixed with `-types`. + + +**Required Packages for Types** + + +| Name | Types Package | Version | +| ---- | ------- | ------- | +| [ember-data](https://github.com/emberjs/data/blob/main/packages/-ember-data/README.md) | ember-data-types | ![NPM Canary Version](https://img.shields.io/npm/v/ember-data-types/canary?label=&color=90EE90) | +| [@ember-data/adapter](https://github.com/emberjs/data/blob/main/packages/adapter/README.md) | @ember-data-types/adapter | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/adapter/canary?label=&color=90EE90) | +| [@ember-data/graph](https://github.com/emberjs/data/blob/main/packages/graph/README.md) | @ember-data-types/graph | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/graph/canary?label=&color=90EE90) | +| [@ember-data/json-api](https://github.com/emberjs/data/blob/main/packages/json-api/README.md) | @ember-data-types/json-api | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/json-api/canary?label=&color=90EE90) | +| [@ember-data/legacy-compat](https://github.com/emberjs/data/blob/main/packages/legacy-compat/README.md) | @ember-data-types/legacy-compat | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/legacy-compat/canary?label=&color=90EE90) | +| [@ember-data/model](https://github.com/emberjs/data/blob/main/packages/model/README.md) | @ember-data-types/model | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/model/canary?label=&color=90EE90) | +| [@ember-data/request](https://github.com/emberjs/data/blob/main/packages/request/README.md) | @ember-data-types/request | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/request/canary?label=&color=90EE90) | +| [@ember-data/request-utils](https://github.com/emberjs/data/blob/main/packages/request-utils/README.md) | @ember-data-types/request-utils | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/request-utils/canary?label=&color=90EE90) | +| [@ember-data/serializer](https://github.com/emberjs/data/blob/main/packages/serializer/README.md) | @ember-data-types/serializer | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/serializer/canary?label=&color=90EE90) | +| [@ember-data/store](https://github.com/emberjs/data/blob/main/packages/store/README.md) | @ember-data-types/store | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/store/canary?label=&color=90EE90) | +| [@ember-data/tracking](https://github.com/emberjs/data/blob/main/packages/tracking/README.md) | @ember-data-types/tracking | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/tracking/canary?label=&color=90EE90) | +| [@warp-drive/core-types](https://github.com/emberjs/data/blob/main/packages/core-types/README.md) | @warp-drive-types/core-types | ![NPM Canary Version](https://img.shields.io/npm/v/%40warp-drive-types/core-types/canary?label=&color=90EE90) | + +> [!WARNING] +> When consuming types in this way, you may sometimes +> encounter a misalignment between the types and the actual API. These misalignments should be rare for 4.12.* => 5.4.*. Overall, even when these misalignments occur, we suspect there are fewer mistakes or issues with these types than in the DefinitelyTyped types. + +Here's an example change to package.json which drops all use of types from `@types/` for both Ember and EmberData and adds the appropriate canary packages. + +```diff +- "@types/ember": "4.0.11", +- "@types/ember-data": "4.4.16", +- "@types/ember-data__adapter": "4.0.6", +- "@types/ember-data__model": "4.0.5", +- "@types/ember-data__serializer": "4.0.6", +- "@types/ember-data__store": "4.0.7", +- "@types/ember__application": "4.0.11", +- "@types/ember__array": "4.0.10", +- "@types/ember__component": "4.0.22", +- "@types/ember__controller": "4.0.12", +- "@types/ember__debug": "4.0.8", +- "@types/ember__destroyable": "4.0.5", +- "@types/ember__engine": "4.0.11", +- "@types/ember__error": "4.0.6", +- "@types/ember__helper": "4.0.7", +- "@types/ember__modifier": "4.0.9", +- "@types/ember__object": "4.0.12", +- "@types/ember__owner": "4.0.9", +- "@types/ember__routing": "4.0.22", +- "@types/ember__runloop": "4.0.10", +- "@types/ember__service": "4.0.9", +- "@types/ember__string": "3.16.3", +- "@types/ember__template": "4.0.7", +- "@types/ember__test": "4.0.6", +- "@types/ember__utils": "4.0.7", ++ "@ember-data-types/adapter": "^5.4.0-alpha.52", ++ "@ember-data-types/model": "^5.4.0-alpha.52", ++ "@ember-data-types/serializer": "^5.4.0-alpha.52", ++ "@ember-data-types/store": "^5.4.0-alpha.52", ++ "@ember-data-types/graph": "^5.4.0-alpha.52", ++ "@ember-data-types/json-api": "^5.4.0-alpha.52", ++ "@ember-data-types/legacy-compat": "^5.4.0-alpha.52", ++ "@ember-data-types/request": "^5.4.0-alpha.52", ++ "@ember-data-types/request-utils": "^5.4.0-alpha.52", ++ "@ember-data-types/tracking": "^5.4.0-alpha.52", ++ "@warp-drive-types/core-types": "^0.0.0-alpha.38", + "ember-data": "^4.12.7", ++ "ember-data-types": "^5.4.0-alpha.52", +``` From a100c2265c5680c2300fce37a44bb1b905aa37b0 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 16:56:56 -0700 Subject: [PATCH 05/10] restructure --- guides/typescript/0-installation.md | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/guides/typescript/0-installation.md b/guides/typescript/0-installation.md index 560e4307713..4b902c46f0d 100644 --- a/guides/typescript/0-installation.md +++ b/guides/typescript/0-installation.md @@ -4,26 +4,31 @@ > EmberData's Native Types require the use of Ember's > Native Types. -There are currently two ways to gain access to EmberData's native types. - -1) [Use Canary](#using-canary) - -2) [Use Official Types Packages](#using-types-packages) -with releases `>= 4.12.*` - - > [!CAUTION] > EmberData does not maintain the DefinitelyTyped types for > EmberData (e.g. the `@types/ember-data__*`). If you were > previously using these, you should uninstall them first. -### Using Canary - > [!IMPORTANT] > Type definitions need to be installed top-level, this means > you have to install every EmberData package `ember-data` > depends on. +> [!TIP] +> When installing packages, use the `@canary` dist tag to get the latest +> version. E.g. `pnpm install ember-data@canary` + +There are currently two ways to gain access to EmberData's native types. + +1) [Use Canary](#using-canary) + +2) [Use Official Types Packages](#using-types-packages) +with releases `>= 4.12.*` + +--- + +### Using Canary + Required Packages for Canary Types | Name | Version | @@ -94,11 +99,6 @@ Here's an example change to package.json which drops all use of types from `@typ ### Using Types Packages -> [!IMPORTANT] -> Type definitions need to be installed top-level, this means -> you have to install types for every EmberData package -> `ember-data` depends on. - Every package in the project that ships types also publishes its types under a second package name. This enables older releases to consume these types instead of relying on the DefinitelyTyped project. From d238aa14fe29626ec29a52c854e71abd0497c32b Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 16:57:36 -0700 Subject: [PATCH 06/10] restructure --- guides/typescript/0-installation.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/guides/typescript/0-installation.md b/guides/typescript/0-installation.md index 4b902c46f0d..bbd4dd036f6 100644 --- a/guides/typescript/0-installation.md +++ b/guides/typescript/0-installation.md @@ -1,14 +1,14 @@ # Installation -> [!TIP] -> EmberData's Native Types require the use of Ember's -> Native Types. - > [!CAUTION] > EmberData does not maintain the DefinitelyTyped types for > EmberData (e.g. the `@types/ember-data__*`). If you were > previously using these, you should uninstall them first. +> [!IMPORTANT] +> EmberData's Native Types require the use of Ember's +> Native Types. + > [!IMPORTANT] > Type definitions need to be installed top-level, this means > you have to install every EmberData package `ember-data` From a2a8a6115cf6b1d856711760fca7dc26bae8760a Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 17:01:19 -0700 Subject: [PATCH 07/10] add install command --- guides/typescript/0-installation.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/guides/typescript/0-installation.md b/guides/typescript/0-installation.md index bbd4dd036f6..4a7553f6b53 100644 --- a/guides/typescript/0-installation.md +++ b/guides/typescript/0-installation.md @@ -46,6 +46,12 @@ Required Packages for Canary Types | [@ember-data/tracking](https://github.com/emberjs/data/blob/main/packages/tracking/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data/tracking/canary?label=&color=90EE90) | | [@warp-drive/core-types](https://github.com/emberjs/data/blob/main/packages/core-types/README.md) | ![NPM Canary Version](https://img.shields.io/npm/v/%40warp-drive/core-types/canary?label=&color=90EE90) | +Here's a single install command for pnpm. Swap pnpm for yarn or npm as needed. + +``` +pnpm install ember-data@canary @ember-data/adapter@canary @ember-data/graph@canary @ember-data/json-api@canary @ember-data/legacy-compat@canary @ember-data/model@canary @ember-data/request@canary @ember-data/request-utils@canary @ember-data/serializer@canary @ember-data/store@canary @ember-data/tracking@canary @warp-drive/core-types@canary +``` + Here's an example change to package.json which drops all use of types from `@types/` for both Ember and EmberData and adds the appropriate canary packages. ```diff @@ -127,6 +133,12 @@ These types-only packages have the same version number as the version they were > When consuming types in this way, you may sometimes > encounter a misalignment between the types and the actual API. These misalignments should be rare for 4.12.* => 5.4.*. Overall, even when these misalignments occur, we suspect there are fewer mistakes or issues with these types than in the DefinitelyTyped types. +Here's a single install command for pnpm. Swap pnpm for yarn or npm as needed. + +``` +pnpm install ember-data-types@canary @ember-data-types/adapter@canary @ember-data-types/graph@canary @ember-data-types/json-api@canary @ember-data-types/legacy-compat@canary @ember-data-types/model@canary @ember-data-types/request@canary @ember-data-types/request-utils@canary @ember-data-types/serializer@canary @ember-data-types/store@canary @ember-data-types/tracking@canary @warp-drive-types/core-types@canary +``` + Here's an example change to package.json which drops all use of types from `@types/` for both Ember and EmberData and adds the appropriate canary packages. ```diff From 7a05bf18b63301fac171a6d584b0991bc545815d Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 17:01:59 -0700 Subject: [PATCH 08/10] move warning --- guides/typescript/0-installation.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/guides/typescript/0-installation.md b/guides/typescript/0-installation.md index 4a7553f6b53..809b0fbfefe 100644 --- a/guides/typescript/0-installation.md +++ b/guides/typescript/0-installation.md @@ -105,6 +105,11 @@ Here's an example change to package.json which drops all use of types from `@typ ### Using Types Packages +> [!WARNING] +> When consuming types in this way, you may sometimes +> encounter a misalignment between the types and the actual API. These misalignments should be rare for 4.12.* => 5.4.*. Overall, even when these misalignments occur, we suspect there are fewer mistakes or issues with these types than in the DefinitelyTyped types. + + Every package in the project that ships types also publishes its types under a second package name. This enables older releases to consume these types instead of relying on the DefinitelyTyped project. @@ -129,10 +134,6 @@ These types-only packages have the same version number as the version they were | [@ember-data/tracking](https://github.com/emberjs/data/blob/main/packages/tracking/README.md) | @ember-data-types/tracking | ![NPM Canary Version](https://img.shields.io/npm/v/%40ember-data-types/tracking/canary?label=&color=90EE90) | | [@warp-drive/core-types](https://github.com/emberjs/data/blob/main/packages/core-types/README.md) | @warp-drive-types/core-types | ![NPM Canary Version](https://img.shields.io/npm/v/%40warp-drive-types/core-types/canary?label=&color=90EE90) | -> [!WARNING] -> When consuming types in this way, you may sometimes -> encounter a misalignment between the types and the actual API. These misalignments should be rare for 4.12.* => 5.4.*. Overall, even when these misalignments occur, we suspect there are fewer mistakes or issues with these types than in the DefinitelyTyped types. - Here's a single install command for pnpm. Swap pnpm for yarn or npm as needed. ``` From be6c8f156aa1b4c1a1ffc1d80fea1aa7d3de6c11 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 17:09:53 -0700 Subject: [PATCH 09/10] fillout configuration section --- guides/typescript/1-configuration.md | 61 +++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/guides/typescript/1-configuration.md b/guides/typescript/1-configuration.md index aa5fa96d928..28c821f53ef 100644 --- a/guides/typescript/1-configuration.md +++ b/guides/typescript/1-configuration.md @@ -9,14 +9,65 @@ option you chose. 2) [Use Official Types Packages](#using-types-packages) with releases `>= 4.12.*` - -> [!CAUTION] -> EmberData does not maintain the DefinitelyTyped types for -> EmberData (e.g. the `@types/ember-data__*`). If you were -> previously using these, you should uninstall them first. +> [!IMPORTANT] +> EmberData's Native Types require the use of Ember's +> Native Types, the configuration below will also setup +> Your application to consume Ember's Native Types. ### Using Canary +To consume `alpha` stage types, you must import the types in your project's `tsconfig.json`. + +For alpha stage types, we add `unstable-preview-types` to the path to help you remember the +potential volatility. +```diff + { + "compilerOptions": { ++ "types": [ ++ "ember-source/types", ++ "ember-data/unstable-preview-types", ++ "@ember-data/store/unstable-preview-types", ++ "@ember-data/adapter/unstable-preview-types", ++ "@ember-data/graph/unstable-preview-types", ++ "@ember-data/json-api/unstable-preview-types", ++ "@ember-data/legacy-compat/unstable-preview-types", ++ "@ember-data/request/unstable-preview-types", ++ "@ember-data/request-utils/unstable-preview-types", ++ "@ember-data/model/unstable-preview-types", ++ "@ember-data/serializer//unstable-preview-types", ++ "@ember-data/tracking/unstable-preview-types", ++ "@warp-drive/core-types/unstable-preview-types" ++ ] + } + } +``` ### Using Types Packages + +To consume `alpha` stage types, you must import the types in your project's `tsconfig.json`. + +For alpha stage types, we add `unstable-preview-types` to the path to help you remember the +potential volatility. + +```diff + { + "compilerOptions": { ++ "types": [ ++ "ember-source/types", ++ "ember-data-types/unstable-preview-types", ++ "@ember-data-types/store/unstable-preview-types", ++ "@ember-data-types/adapter/unstable-preview-types", ++ "@ember-data-types/graph/unstable-preview-types", ++ "@ember-data-types/json-api/unstable-preview-types", ++ "@ember-data-types/legacy-compat/unstable-preview-types", ++ "@ember-data-types/request/unstable-preview-types", ++ "@ember-data-types/request-utils/unstable-preview-types", ++ "@ember-data-types/model/unstable-preview-types", ++ "@ember-data-types/serializer//unstable-preview-types", ++ "@ember-data-types/tracking/unstable-preview-types", ++ "@warp-drive-types/core-types/unstable-preview-types" ++ ] + } + } +``` From fa0df2d9ef39a9c2135e1fcff7f404df363e343c Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 5 Apr 2024 17:55:02 -0700 Subject: [PATCH 10/10] more types --- guides/typescript/2-why-brands.md | 73 +++++++++++++ guides/typescript/3-typing-models.md | 155 +++++++++++++++++++++++++++ guides/typescript/index.md | 3 +- 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 guides/typescript/2-why-brands.md create mode 100644 guides/typescript/3-typing-models.md diff --git a/guides/typescript/2-why-brands.md b/guides/typescript/2-why-brands.md new file mode 100644 index 00000000000..beea79975d0 --- /dev/null +++ b/guides/typescript/2-why-brands.md @@ -0,0 +1,73 @@ +# EmberData's Types Strategy + +If you previously used the EmberData types provided by DefinitelyTyped, one MASSIVE +difference you will notice immediately is that EmberData does not use any registries +for types. + +Instead, EmberData uses Symbol keys to brand objects with additional type information. + +For example: + +```ts +import Model, { attr } from '@ember-data/model'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @attr declare name: string; + + [ResourceType] = 'user' as const; +} +``` + +This means that when calling an API that takes in a resource type, we pass this branded class as a generic instead of relying on registries. For example: + +```ts +import type User from 'my-app/models/user'; + +// ... + +const user = await store.findRecord('user', '1'); +``` + +We chose this direction over registries or objects for a number of reasons we'll detail below. + +### Why not registries? + +We found registries had 5 significant drawbacks. + +First, registries have a max number of entries before TypeScript begins resolving unions based on the registry as `any`. This limit is relatively low (in the hundreds) so many applications hit into this relatively quickly. + +Second, constructing registries is brittle. Conflicts often arise when attempting to source models from additional libraries, and often result in `never` types due to an empty registry. + +Third, we couldn't type EmberData itself using registries without adopting extreme complexity. This is because while DefinitelyTyped could assume one single global registry, EmberData cannot. This arises for a myriad of reasons: EmberData supports multiple stores, multiple sources of schema, and our own test suite defines Models for each test that would conflict with each other if we were forced to use a single global registry. + +Fourth, and possibly most importantly, registries assume that for a given resource-type (like `'user'`) that only a single type signature exists. While this has *mostly* been true historically in EmberData, it is no longer true and will become increasingly less true as we roll out additional features we have planned. Supporting different +type signatures for Create/Edit/Delete as well as for partials and actions means if we stuck with registries, we'd need tons of them and things would get complicated quickly. + +Fifth, the registry approach prevents static analysis from easily determining where in the application a Model or Schema is in use, making it difficult for bundlers to +optimize while code-splitting. + +### Ok, so then why not objects? + +A common alternative to registries is to pass classes as tokens into an API. For instance, we could have redesigned +EmberData to take a class instead of a string in the call to `findRecord` below. + +```ts +import type User from 'my-app/models/user'; + +// ... + +const user = await store.findRecord(User, '1'); +``` + +There are two significant drawbacks to this approach. The first is one of the same reasons as "why not registries": we expect that lots of type signatures will satisfy a single resource-type in the future. + +The second is related and more important: it forces you to use classes or other objects to represent data, which we don't want to do. + +In the near future, EmberData will switch the default story for presenting data from `Model` which is a class-per-resource approach to `SchemaRecord`, which is a single class capable of presenting the data for any associated schema. Schema's are defined in `json` and can be loaded into the app in any number of ways. That means when using SchemaRecord, there never would be a class to import and use as a token for such a call. + +### Ok, Brands! + +Brands solve the various issues mentioned above, and a bit more! + +Over time, they should enable us to curate a great experience for working with partials, actions, contrained edit signatures, query syntaxes like GraphQL and more. diff --git a/guides/typescript/3-typing-models.md b/guides/typescript/3-typing-models.md new file mode 100644 index 00000000000..db92dbabea0 --- /dev/null +++ b/guides/typescript/3-typing-models.md @@ -0,0 +1,155 @@ +# Typing Models + +## ResourceType + +Example: add the `ResourceType` brand to the `user` model. + +```ts +import Model, { attr } from '@ember-data/model'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @attr declare name: string; + + [ResourceType] = 'user' as const; +} +``` + +## Transforms + +Transforms with a `TransformName` brand will have their type and options validated. Once we move to stage-3 decorators, the signature of the field would also be validated against the transform. + +Example: Using Transforms + +```ts +import Model, { attr } from '@ember-data/model'; +import type { StringTransform } from '@ember-data/serializer/transforms'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @attr('string') declare name: string; + + [ResourceType] = 'user' as const; +} +``` + +## Sync BelongsTo + +`belongsTo` relationships will have their resource type and options config validated against the passed in type. + +Once we move to stage-3 decorators, explicitly setting the generic would not be required as it could be infered from the field's type. + +```ts +import Model, { belongsTo } from '@ember-data/model'; +import type Address from './address'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @belongsTo
('address', { async: false, inverse: null }) + declare address: Address; + + [ResourceType] = 'user' as const; +} +``` + +## Async BelongsTo + +`belongsTo` relationships will have their resource type and options config validated against the passed in type. + +Once we move to stage-3 decorators, explicitly setting the generic would not be required as it could be infered from the field's type. + +```ts +import Model, { belongsTo, AsyncBelongsTo } from '@ember-data/model'; +import type Address from './address'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @belongsTo
('address', { async: true, inverse: null }) + declare address: AsyncBelongsTo
; + + [ResourceType] = 'user' as const; +} +``` + +## Sync HasMany (data only) + +If you don't need access to meta or links on relationships, you can type the relationship as just an array. + +`hasMany` relationships will have their resource type and options config validated against the passed in type. + +Once we move to stage-3 decorators, explicitly setting the generic would not be required as it could be infered from the field's type. + +```ts +import Model, { hasMany } from '@ember-data/model'; +import type Post from './post'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @hasMany('post', { async: false, inverse: 'author' }) + declare posts: Post[]; + + [ResourceType] = 'user' as const; +} +``` + +## Sync HasMany (with meta, links, etc) + +`hasMany` relationships will have their resource type and options config validated against the passed in type. + +Once we move to stage-3 decorators, explicitly setting the generic would not be required as it could be infered from the field's type. + +```ts +import Model, { hasMany, ManyArray } from '@ember-data/model'; +import type Post from './post'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @hasMany('post', { async: false, inverse: 'author' }) + declare posts: ManyArray; + + [ResourceType] = 'user' as const; +} +``` + +## Async HasMany (restricted) + +If you don't need access to meta, links or template iterations on relationships, you can type the relationship as just a promise resolving to an array. Only use this if the value +will always be awaited before iteration. + +`hasMany` relationships will have their resource type and options config validated against the passed in type. + +Once we move to stage-3 decorators, explicitly setting the generic would not be required as it could be infered from the field's type. + +```ts +import Model, { hasMany, AsyncHasMany } from '@ember-data/model'; +import type Post from './post'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @hasMany('post', { async: true, inverse: 'author' }) + declare posts: Promise; + + [ResourceType] = 'user' as const; +} +``` + +`Promise>` also works. + +## Async HasMany (with links, meta, etc.) + +`hasMany` relationships will have their resource type and options config validated against the passed in type. + +Once we move to stage-3 decorators, explicitly setting the generic would not be required as it could be infered from the field's type. + +```ts +import Model, { hasMany, AsyncHasMany } from '@ember-data/model'; +import type Post from './post'; +import { ResourceType } from '@warp-drive/core-types/symbols'; + +export default class User extends Model { + @hasMany('post', { async: true, inverse: 'author' }) + declare posts: AsyncHasMany; + + [ResourceType] = 'user' as const; +} +``` diff --git a/guides/typescript/index.md b/guides/typescript/index.md index 1b531263671..3769b20a960 100644 --- a/guides/typescript/index.md +++ b/guides/typescript/index.md @@ -16,7 +16,8 @@ the following two sections - [Using Canary](./1-configuration.md#using-canary) - [Using Types Packages](./1-configuration.md#using-types-packages) - Usage - - Typing Models + - [Why Brands](./2-why-brands.md) + - [Typing Models](./3-typing-models.md) - Typing Transforms - Typing Requests - Typing Builders