Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline type annotations for destructured properties using angle bracket syntax #58633

Closed
6 tasks done
Not-Jayden opened this issue May 23, 2024 · 3 comments
Closed
6 tasks done

Comments

@Not-Jayden
Copy link

🔍 Search Terms

inline type annotations, type annotations, destructuring annotations, destructuring, property annotations, parameter destructuring,

✅ Viability Checklist

⭐ Suggestion

I've observed a lot of discussion around the verbosity/duplication involved when providing type annotations for destructured object properties (particularly re-ignited by this Svelte issue), which prompted me to wonder if this could be resolved with additional syntax being introduced to TypeScript.

The proposal suggests introducing new syntax for adding inline type annotations using angle brackets <T> within destructuring assignments that can be added immediately after the property keys, along with a new optional modifier keyword to indicate a property as optional.

e.g. this

// before
function fetchData({
    url,
    method = "GET",
    timeout = 0
}: {
    url: string;
    method?: string;
    timeout?: number;
}) {
    console.log(`Fetching data from ${url} with method ${method} and timeout ${timeout}`);
}

// after
function fetchData({
  url<string>,
  method<optional string> = "GET",
  timeout<optional number> = 0
}) {
  console.log(`Fetching data from ${url} with method ${method} and timeout ${timeout}`);
}

For completeness (though far less valuable), this could probably also support providing annotations in array destructuring assignments as well. e.g.

// before
function processCoordinates([x, y, z]: [number, number, number]) {
  console.log(`Coordinates are x: ${x}, y: ${y}, z: ${z}`);
}

// after
function processCoordinates([x<number>, y<number>, z<number>]) {
  console.log(`Coordinates are x: ${x}, y: ${y}, z: ${z}`);
}

Advantages:

  1. Readability when destructuring is improved as the types are colocated directly next to each of the destructured properties.
  2. Less verbose/redundancy as you don't have to declare destructured properties twice.

Drawbacks:

  1. The angle bracket syntax might introduce more confusion to understanding TypeScript syntax, given it is already being used for both generics and type casting.
  2. This is a non-backwards compatible breaking change to TypeScript.

Other considerations:

  1. Should the optional modifier keyword also work inside of object literal types.
  2. Could a ? be used instead of the new optional modifier inside/outside of the brackets (e.g. url?<string> or url<string?>). Would probably be more familiar to the way optional properties are defined now, but it might get confusing whether ? is part of the property name in the first example, or part of conditional logic in the second.

📃 Motivating Example

Drawing inspiration from the Svelte $props issue linked above, a React equivalent example might look like:

// before
const Button = ({
  label,
  size = 'medium',
  onClick,
  disabled = false
}: {
  label: string;
  size?: 'small' | 'medium' | 'large';
  onClick?: () => void;
  disabled?: boolean;
}) => {
  return (
    <button 
      className={`btn ${size}`} 
      onClick={onClick} 
      disabled={disabled}
    >
      {label}
    </button>
  );
};

// after
const Button = ({
  label<string>,
  size<optional 'small' | 'medium' | 'large'> = 'medium',
  onClick<optional () => void>,
  disabled<optional boolean> = false
}) => {
  return (
    <button 
      className={`btn ${size}`} 
      onClick={onClick} 
      disabled={disabled}
    >
      {label}
    </button>
  );
};

💻 Use Cases

  1. What do you want to use this for?

Reducing duplication whenever needing to do destructuring assignments with type annotations. In particular it will solve the Svelte issue linked above, but applies anywhere you use destructuring and type annotations that you commonly see with function arguments.

  1. What shortcomings exist with current approaches?

As discussed above already, it's unnecessarily verbose and duplicative, and prevents the colocation of types where you probably want to see them.

  1. What workarounds are you using in the meantime?

Move the type declarations for destructured function params above/outside of the destructuring assignment, but this isn't actually addressing the problems solved by the new syntax.

@whzx5byb
Copy link

Related: #29526.

@Not-Jayden
Copy link
Author

Thanks @whzx5byb, will close as a duplicate

@fatcerberus
Copy link

Related: #29526.

Wow that comment thread turned into a trainwreck at the end there. It seems to have completely devolved to “why you just shouldn’t use destructuring at all, and then you won’t need this feature” which is just… not productive at all

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants