microsoft / microsoft/TypeScript

Remove key from object after `delete object.key`

Offen
#53,697 5 Kommentare 3 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Awaiting More Feedback Suggestion
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.4k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

Suggestion

🔍 Search Terms

delete
delete key
narrowing
narrowing delete

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

In TypeScript, it's already possible to have objects add keys to their types using if ("key" in object) // object: { key: unknown }. It is not currently possible to do the exact opposite: deleting a key off of an object.

This could be achieved in two ways:

  • Guaranteed: type { key: string }; delete object.key; type { }.
  • Optional: type { key?: string | undefined }; if (object.key === undefined) delete object.key; type { key?: string }.

The guaranteed way is pretty straight forward: it removes the key entirely.
The optional way is slightly more tricky: it should only remove the type information checked in the if statement. Remaining type options should still exist after the if statement. If the last remaining type option is removed, then it should function the same as the guaranteed way.

Naturally, if the key didn't exist on the object in the first place, the type information should remain the exact same as before.

📃 Motivating Example

I'm using the zod library, with which I set a value on object user as { givenName: string; infix?: string | undefined; surname: string; }.
I wrote a factory function toUser({ givenName, infix, surname }: { givenName: string; infix?: string; surname: string; }): User { ... }.
The type infix?: string | undefined is not compatible with type infix?: string.
image

--- EDIT: Extra example ---
After executing delete object.key, I'm expecting the type information to no longer contain this key:

  const myObject: { key1?: string | undefined, key2?: string | undefined } = { ... };
  delete myObject.key1; // Type should now become: { key2?: string | undefined}
  myObject.key1 // Should error, key was deleted

Now, if I want to remove a key under certain conditions:

  const myObject: { key1?: string | number | undefined } = { ... };
  if (typeof myObject.key1 === "number") delete myObject.key1; // Removes "number" from types. This already works.
  if (typeof myObject.key1 === "undefined") delete myObject.key1; // Removes "undefined" from type definition. This does not work yet.
  if (typeof myObject.key1 === "string") delete myObject.key1; // Removes the last type; "key1" will no longer exist on object.

In the above example, the native types "number" and "string" get stripped off as expected. The type "undefined" however, does not. This breaks the tsconfig option exactOptionalPropertyTypes as the key should now no longer be able to exist. It cannot exist with literal value undefined.

💻 Use Cases

This is purely type information, but it seems essential if the typing system is to remain correct after the delete keyword.
For the time being, I'll have to set the type to infix?: string | undefined, knowing it's not entirely accurate (key "infix" should not be permitted with value "undefined").

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Es werden keine Implementierungsdateien oder Tests genannt. Beginne damit, die garantierten und optionalen delete-Beispiele in einem TypeScript-Test nachzubilden, und vergleiche dann das aktuelle Narrowing-Verhalten mit den angeforderten Typen nach dem Löschen; fertig ist die Aufgabe, wenn der Checker diese Fälle ohne Änderung des erzeugten JavaScript verarbeitet.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.