Skip to content

Type all exported members according to some interfaceΒ #59965

Closed as not planned
Closed as not planned
@ravinggenius

Description

@ravinggenius

πŸ” Search Terms

  • "type export with" keyword combination.
  • quality of life change

βœ… Viability Checklist

⭐ Suggestion

Allow typing all exported tokens as if they were members of some defined interface or type.

// interface.ts
export interface Person {
  age?: number;
  name: string;
}
// my-person.ts
import { Person } from "./interface";

// this is new and does the following
// require all exports to be one of the member properties of Person
// enables autocomplete on exported token names
// types exported tokens according to matching member names in Person
type export with Person;

// this named export is required and must be a string
export const name = "Foo";

// this named export is optional, but if defined must be a number
export const age = 42;

// not sure if other exports should be allowed
// other.ts

import * as person from "./my-person";

// person has type Person as defined in interface.ts

πŸ“ƒ Motivating Example

Next.js has many files which it looks for. Next expects these files to export members conforming to its own interface. Currently it's up to developer to type each individual member separately. These types need to be separately imported from Next as well. Documentation (if it exists) needs to be consulted for each expected member export.

type export with solves or improves many of these issues. type export with defines what tokens should be exported, so auto-complete can be used to fill in names after typing export const .... Furthermore it defines types for each of these tokens, so individual tokens don't need to be independently typed.

Here's an example of what is currently needed to properly type a layout.

import { Metadata } from "next";
import { ReactNode } from "react";

export const generateMetadata = async () => {
	const { t } = await loadPageTranslations("layout-root");

	return {
		title: t("title"),
		description: t("description")
	} satisfies Metadata as Metadata;
};

export default async function RootLayout({
	children
}: {
	children: ReactNode;
	// other props must be individually typed
}) {
	// nothing verifies the component return type
	return (
		<html>
			<body>
				<main>{children}</main>
			</body>
		</html>
	);
}

Here's how this file could be typed with this proposal.

import { LayoutFile } from "next";

type export with LayoutFile;

// generateMetadata is optional
// if defined it must be an async function with a return value of a specific shape
// `generateMetadata` is also mutually exclusive with `metadata`, so error if both are defined
export const generateMetadata = async () => {
	const { t } = await loadPageTranslations("layout-root");

	// return object key names are autocompleted and values are type-checked
	return {
		title: t("title"),
		description: t("description")
	};
};

// default export is required to be defined by LayoutFile and must satisfy React's component type with proper typings for expected props
export default async function RootLayout({ children }) {
	return (
		<html>
			<body>
				<main>{children}</main>
			</body>
		</html>
	);
}

πŸ’» Use Cases

  1. What do you want to use this for? I want strict type-checking with as little friction as possible. This would be especially helpful for frameworks that expect certain files to define certain exports.
  2. What shortcomings exist with current approaches? Assuming types are provided, each individual export in a file needs to be typed separately. There is no mechanism to verify exports conform to a particular interface.
  3. What workarounds are you using in the meantime? Importing multiple types and using them ad-hoc to check exported members, as shown above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions