microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.31k stars 12.39k forks source link

lib.dom.d.ts: HTMLInputElement::type should be more specific than just 'string' #41154

Open ArcticZeroo opened 3 years ago

ArcticZeroo commented 3 years ago

Search Terms

Suggestion

In lib.dom.d.ts, HTMLInputElement::type is currently specified as a string, but its value can only legally be one of a known set of strings (specified on MDN). I would like to change this property to be a union of string literals that expresses this set of strings.

Use Cases

Currently, code which assumes string is assignable to HTMLInputElement.type is operating on a bad assumption which is not actually safe. By restricting the allowed strings in this property, we get benefits including:

Examples

const inputElement = document.createElement('input');
inputElement.type = 'cat'; // should be illegal
inputElement.type = 123456; // already illegal (not assignable to 'string')
inputElement.type = '123456'; // should be illegal
inputElement.type = 'text'; // should be legal

Checklist

My suggestion meets these guidelines:

RyanCavanaugh commented 3 years ago

I'm a little concerned about the breaking aspect of this given that this is probably rarely set by code in the first place. Open to more feedback though

tjjfvi commented 3 years ago

It only breaks assignments (because "button" | "color" | "checkbox" | ... is assignable to string), so if code doesn't ever really set it, then it wouldn't really be an impactful breaking change, right?

ArcticZeroo commented 3 years ago

I think it's pretty likely that most code dynamically creating input elements is setting type directly with a known literal, instead of passing it in somehow via string.

The use case of needing to manipulate an input's type in general seems pretty common to me -- along with needing the ability to set type when dynamically creating inputs, imagine something like a "show password" button which toggles between type="text" and type="password".

The main unknown here is how much code is actually trying to assign string without a known literal type, and I'd guess (without any data to back it up though) that this is a pretty uncommon use case in comparison to the known literal.

For reference, something like the following would be subject to the breaking change:

const createInput = (type: string) => {
    const inputElement = document.createElement('input);
    inputElement.type = type;
    // do some other setup for this element so it's not 2 lines πŸ€·β€β™€οΈ
    return inputElement;
};
antsif-a commented 2 years ago

Quite an old issue, but I also found that type: string already conflicts with React's JSX, as React already has specific declaration of type. For example, the following would not compile:

import React, { HTMLProps } from 'react';

function Button({ ...props }: HTMLProps<HTMLButtonElement>)  {
    return (
        <button { ...props } />
    );
};

Error: Type 'string' is not assignable to type '"button" | "submit" | "reset" | undefined'.