amzn / style-dictionary

A build system for creating cross-platform styles.
https://styledictionary.com
Apache License 2.0
3.93k stars 558 forks source link

Types Resolve as `any` for TypeScript<5.x.x #1371

Closed zacowan closed 2 weeks ago

zacowan commented 1 month ago

Description

When importing types from style-dictionary/types, TypeScript versions less than 5.x.x cannot resolve what the types are supposed to be. As a result, the types resolve as any.

To Reproduce

  1. Initialize an empty node project
  2. Install the previous major version of TypeScript
npm add -D typescript@4
  1. Initialize the tsconfig.json
npm exec tsc -- --init
  1. Install style-dictionary@4.1.3
npm add -D style-dictionary@4.1.3
  1. Add a file with a type import
// src/index.ts
import type { TransformedToken } from 'style-dictionary/types';
  1. Notice that TransformedToken resolves as any

Additional Context

Node Version: 18.18.1

If you are using VSCode to inspect the resolved types, you'll need to adjust the settings to use the installed version of TypeScript, rather than the one shipped with VSCode.

// .vscode/settings.json
{
  "typescript.tsdk": "node_modules/typescript/lib"
}
jorenbroekema commented 4 weeks ago

You'll need to configure your tsconfig to handle package entrypoints:

{
  "module": "NodeNext",
  "moduleResolution": "NodeNext"
}

for moduleResolution, "Bundler" also works in case you have relative extensionless imports and you don't want to migrate yet to using extensions. https://www.typescriptlang.org/tsconfig/#moduleResolution

zacowan commented 3 weeks ago

You'll need to configure your tsconfig to handle package entrypoints:

{
  "module": "NodeNext",
  "moduleResolution": "NodeNext"
}

for moduleResolution, "Bundler" also works in case you have relative extensionless imports and you don't want to migrate yet to using extensions. https://www.typescriptlang.org/tsconfig/#moduleResolution

Thanks for the quick response @jorenbroekema! This does not work - the types still resolve as any. To clarify - TypeScript seems to be able to locate the file from the package entrypoints (style-dictionary/types), but it cannot then interpret the types that are exported from that file, resulting in all of the types being any. Additionally, Bundler is an option that is not supported on TS<5.x.x 😅

This is reproducible with the same set of instructions above, with the addition on the NodeNext changes you've suggested.

I do see that the types in style-dictionary/types/index.d.ts include .ts extensions - I wonder if that could be related? It looks like the option to support that in TypeScript was included in the release of TypeScript 5.0: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#allowimportingtsextensions

jorenbroekema commented 3 weeks ago

I'm addressing some of the extensions that style-dictionary is using internally https://github.com/amzn/style-dictionary/pull/1374 They'll be more "standard" and not relying on bundler logics to resolve imports just because the extensions don't match the compiled outputs.

You could check if this PR branch solves the issue for you, you'll have to check it out locally, npm run build and use something like npm link to link it into the node_modules of your project, or copy paste the files after build manually.

I'd also recommend upgrading TypeScript to latest, and upgrading it regularly, but I'm also aware that this is often not exactly a drop-in replacement/migration for folks 😅 . It may solve some of the issues though that I know typescript had with resolving modules using modern node resolution algorithm (e.g. package entrypoints, file extension leniency, etc.)

zacowan commented 3 weeks ago

I'm addressing some of the extensions that style-dictionary is using internally #1374 They'll be more "standard" and not relying on bundler logics to resolve imports just because the extensions don't match the compiled outputs.

Gave it a try locally - works great! Seems to work for both esm and cjs setups too, which is a nice touch

I'd also recommend upgrading TypeScript to latest, and upgrading it regularly, but I'm also aware that this is often not exactly a drop-in replacement/migration for folks 😅 . It may solve some of the issues though that I know typescript had with resolving modules using modern node resolution algorithm (e.g. package entrypoints, file extension leniency, etc.)

100% - hopefully soon 🤞 have to work through peer-dependency soup