Support a built-in type for well-formed strings

Open
#60,765 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
28/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Domain
compilers

Research direction

Start with src/lib/es2024.string.d.ts and the existing String.isWellFormed() and String.toWellFormed() declarations. Then investigate how TypeScript handles string literals, type guards, and TextDecoder.decode(); done would include a decided well-formed string type design with corresponding type-checking behavior and tests.

Written by the indexing model from the issue text.

Description

Awaiting More Feedback Suggestion
🔍 Search Terms

"Unicode", "well-formed Unicode", "valid Unicode", "lone surrogates", ""UTF-16", "UTF-8", "isWellFormed()", "toWellFormed()"

✅ Viability Checklist
⭐ Suggestion

ES2024 now has String.isWellFormed() and String.toWellFormed(), which are supported in TypeScript's ES2024 type definitions.

But significant value from these functions is not realized in TypeScript because of the lack of a well-formed string type.

What I'd like to see is a "well-formed string" type (itself a super-type of String) for which isWellFormed() serves as a type guard and toWellFormed() (as well as functions like TextDecoder.decode()) return the well-formed string type.

Additionally, string literals could be determined to be of the well-formed string type at compile time.

This way TypeScript developers could get type safety for scenarios where strings need to be guaranteed to be well-formed.

📃 Motivating Example

I'm working on a TypeScript implementation of CEL which requires passing well-formed UTF-8 strings into an evaluation environment. If I want to bridge TypeScript's type safety to CEL's type safety, I'll need a well-formed string type in TypeScript.

💻 Use Cases

I can do something like this in my project:

interface WellFormedString extends String {
  __brand: "WellFormed";
}

interface String {
  isWellFormed(): this is WellFormedString;
  toWellFormed(): WellFormedString;
  toUpperCase(): this extends WellFormedString ? WellFormedString : string;
  toLowerCase(): this extends WellFormedString ? WellFormedString : string;
}

interface TextDecoder {
  decode(input?: AllowSharedBufferSource, options?: TextDecodeOptions): WellFormedString;
}

function useWellFormedString(a: WellFormedString) {
  // ...
}

// good -- no error
useWellFormedString("hello".toWellFormed());

// good -- no error
useWellFormedString("hello".toWellFormed().toUpperCase());

// good -- no error
const h = "hello";
if (h.isWellFormed()) {
  useWellFormedString(h); 
}

// good -- no error
// (the decoder coerces a lone "WTF-8" surrogate to "\ufffd\ufffd\ufffd")
useWellFormedString(new TextDecoder().decode(new Uint8Array([0xed, 0xba, 0xad])))

// good -- error
// (malformed string with lone UTF-16 surrogate)
useWellFormedString("\udead");

// bad -- error
useWellFormedString("hello");

// bad -- error
useWellFormedString("hello" as WellFormedString);

But there are some significant disadvantages here:

  1. Well-formed string literals are not recognized as well-formed.
  2. Uses a branding hack.
  3. The compiler complains about casting (maybe this is fixable, but I don't know how).
Dominant language
Go
Stars
111k
Forks
14.4k
Avg merge
1d 19h
Merged PRs (30d)
117

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from microsoft/TypeScript

All issues in microsoft/TypeScript

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.