Branding Drafts on Type level
Les mainteneurs répondent en général sous 4 jours
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Accessibilité débutants
- 35/100
- Type d'issue
- Fonctionnalité
- Clarté
- À clarifier
- Activité
- Calme
- Stack technique
- typescript
- Domaine
- developer-experience
Piste de recherche
Commencez par la preuve de concept TypeScript Playground et comparez son comportement concernant branded Draft, MaybeDraft, current, isDraft et produce avec les signatures de types existantes d'Immer. L'issue ne nomme aucun fichier ni test du dépôt ; sa réalisation nécessiterait de décider d'un commun accord si le branding à la compilation est souhaitable et de définir le périmètre de l'implémentation.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
🙋♂ Question
I was wondering if it would be possible to not just brand at runtime, but branded type at compile time as well?
Cause
I was using redux/toolkit, which uses Immer and had an issue where current(val) was called on a non draft, typechecker was fine, executed it in development, all good, came to production, tried to unwrap a non draft and crashed. Not a big deal, just use isDraft, but it was something technically avoidable if....
Implementation
I could make a PR, I just wanted to figure out if that is even desirable since I assume this question came up already some time ago and was decided against it for a reason to me currently unknown (except maybe that some types are already relatively complex)
Proof of concept
I made a small proof of concept on typescript playground relative quickly to just check out the branding, the idea would be that produce etc return Drafted<T> instead of T hiding a potential source for errors (naming still up for discussion)
I made a small code example on TS playground where I do not duplicate the objects, Proxy them etc for simplicity. If no link should be used, here the snipped:
const brand : unique symbol = Symbol("foobar")
type Draft<T> = T & {[brand]:never}
type MaybeDraft<T> = Draft<T> | T
const a = 32;
const b = {
a: 32,
b: "Hello world"
}
const c = [1, 2, 3];
const d = [a,b,c] as const
const draft = <T extends object>(val: T)=> {
const clone = val
Object.defineProperty(clone, brand, {configurable: false, enumerable: false, writable: false, value: true})
return clone as Draft<T>
}
const isDraft = <T extends unknown>(val: T): val is Draft<T> => {
//@ts-ignore
if (val[brand]) {
return true
}
return false
}
const B = draft(b)
const C = draft(c)
const D = draft(d)
console.log("A: ", isDraft(a))
console.log("B: ", isDraft(B))
console.log("C: ", isDraft(C))
console.log("D: ", isDraft(D))
/**
* Accepts a Draft or a Value, but differentiates them on a type level to enforce handling of each of the 2 scenarios
*/
const doSomething = (value: MaybeDraft<number[]>) => {
//const val = current(value) // Error because value could also not be a draft
const val = isDraft(value) ? current(value) : value
return val
}
/**
* Accepts a Draft or a Value, it doesn't care if it might be a Draft and just uses it
*/
const doSomething2 = (value: number[]) => {
return value
}
/**
* Accepts only a Draft, non Drafts are refused on a Type Level at compile time
*/
const current = <T extends object>(value: Draft<T>):T => {
return value
}
doSomething(C)
doSomething2(C)
//const neverHappend = current(c)
const val = current(C)
- Langage dominant
- JavaScript
- Étoiles
- 29k
- Forks
- 905
- Merge moyen
- 3 j 16 h
- PR mergées (30 j)
- 22
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de immerjs/immer
-
Shrinking an array with `length =` and growing it back loses the patches for the truncated indicesPeut-être pris @RClaudiuM l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
Les mainteneurs répondent en général sous 4 jours
-
Difficulté 3/5 1-2 jours Accessibilité débutants 35/100
Les mainteneurs répondent en général sous 4 jours
-
Docs: Chinese (zh-CN) website translation is outdated vs English docsPeut-être à nouveau libre @lijiayou0728 l’a pris il y a 91 jours, et aucune pull request n’est ouverte. Ouverte
Difficulté 4/5 3-5 jours Accessibilité débutants 55/100
immerjs/immer#1242 · 5 commentaires ·
Les mainteneurs répondent en général sous 4 jours
-
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 35/100
immerjs/immer#1217 · 1 commentaire ·
Les mainteneurs répondent en général sous 4 jours
-
[Feature Request] Support for "Splice" patches in arrays for CRDT/Y.js integration (and others)Ouverteproposal
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 25/100
immerjs/immer#1202 · 2 commentaires · 1 réaction ·
Les mainteneurs répondent en général sous 4 jours
Toutes les issues de immerjs/immer
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Automattic/node-canvas#2633 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
capricorn86/happy-dom#2594 ·
Les mainteneurs répondent en général sous 1 jour
-
Decoding tag 1 (epoch date) with an 8-byte integer throws "Cannot mix BigInt and other types"Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 79/100
microsoft/monaco-editor#5575 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
Les mainteneurs répondent en général sous 1 jour