-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
Acknowledgement
- I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.
Comment
Hello!
I asked this question about ten days ago on Stack Overflow, but I didn't get an answer, nor did I get an upvote or a downvote on my post...
Maybe I didn't ask my question properly and wasn't clear enough?
Please, don't hesitate to tell me if it is the case.
I'm going to ask it again here in the hope that I can find an answer as brilliant as the other times I've posted in the TypeScript issues.
I have a question regarding imports with a computed string.
I noticed they seem to be typed as Promise<any>
, but I'd like to know if there's a better way to handle this, so that they could be still typed as Promise<typeof ...>
.
I will try to present the issue with minimal and isolated code snippets first and then provide a use case (to give an example).
When I write an import like this:
import(`@/i18n/locales/${language}`)
I have the impression that the type of import(...)
becomes Promise<any>
.
I deduce this by isolating this import within the assignment of a variable:
const x = () => import(`@/i18n/locales/${'en'}`);
const x: () => Promise<any>
But, when I write:
const x = () => import("@/i18n/locales/en");
Then:
const x: () => Promise<typeof import("/foo/bar/src/i18n/locales/en")>
In the case where it involves string interpolation that is unpredictable, I understand the Promise<any>
.
But in some cases, I think that a similar interpolation can be typed and controlled.
For example, using a sum type:
type LanguageFlag = "en" | "fr" | "it";
const LANGUAGES: LanguageFlag[] = ["en", "fr", "it"];
So, I would like my imports to keep the correct typing on the Promise<>
type argument.
For instance:
// * ... @/i18n/locales/schema
export default {
_infos: {
lng: '',
label: ''
},
navbar: {
assistance: ''
},
auth: {
login: '',
logout: '',
signup: ''
}
// * ...
} as const;
//====================
// * ... Types
//====================
//------------------------
// * ... JSON
//------------------------
type JSONPrimitiveLeafs = string | number | boolean | null;
type JSONLeafs = JSONPrimitiveLeafs | JSONPrimitiveLeafs[];
type TypedLeafsJSONData<LeafsTypes extends JSONLeafs, AllowObjArrays extends 'ALLOW_OBJ_ARRAYS' = never> = {
[_: string]: TypedLeafsJSONData<LeafsTypes> | (AllowObjArrays extends never ? never : TypedLeafsJSONData<LeafsTypes>[]) | LeafsTypes;
};
//------------------------
// * ... Utilitary types
//------------------------
type MakeHomogeneousValuesObjType<Obj extends object, ObjValuesType> = {
[K in keyof Obj]: Obj[K] extends object ? MakeHomogeneousValuesObjType<Obj[K], ObjValuesType> : ObjValuesType;
};
//------------------------
// * ... Locales
//------------------------
import VOCAB_SCHEMA from '@/i18n/locales/schema';
type LocalesObjKey = LanguageFlag;
type VocabObjValue = string;
type VocabBase = typeof VOCAB_SCHEMA;
type VocabType = MakeHomogeneousValuesObjType<VocabBase, VocabObjValue>;
type NextInternationalMagic = {
default: VocabType;
};
type NextInternationalLazyLoadFn = () => Promise<NextInternationalMagic>;
type LanguageFlag = "en" | "fr" | "it";
type LocalesObjEntity = [LocalesObjKey, NextInternationalLazyLoadFn];
type LocalesObj = Record<LocalesObjKey, NextInternationalLazyLoadFn>;
type LocalesGetterConfigObjTypeConstraint = Record<LanguageFlag, () => Promise<TypedLeafsJSONData<VocabObjValue>>>;
//====================
// * ... Generator
//====================
const LANGUAGES: LanguageFlag[] = ["en", "fr", "it"];
export const GENERATED_LOCALES_OBJ = Object.fromEntries(
LANGUAGES.map((language) => [language, () => import(`@/i18n/locales/${language}`)] satisfies LocalesObjEntity)
) as LocalesObj satisfies LocalesGetterConfigObjTypeConstraint;
Here, I am a bit disappointed by this line:
LANGUAGES.map((language) => [language, () => import(`@/i18n/locales/${language}`)] satisfies LocalesObjEntity)
Since the values of language
are predictable:
(parameter) language: "en" | "fr" | "it"
I would have liked having a consistent satisfies LocalesObjEntity
.
But since this import is typed as Promise<any>
, the satisfies operator is currently completely useless.
If the Promise
type argument could be: <typeof .../en ; typeof .../fr ; typeof .../it>
the satisfies operator could validate or invalidate the imports.
So, I would like to know: is there a compilation flag I could add, or could I be even stricter and still allowing the possibility of using string interpolations?
Thank you in advance for your responses!