Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why autocomplete stop working in an object with type in TypeScript?

I have a list of routes in one object and want to import it in other file and have autocomplete for object properties.

index.ts

import allRoutes from './routes';

allRoutes.routeHome;

routes.ts

const allRoutes = {
  routeHome: '',
  routePortfolio: 'portfolio'
};

export default allRoutes; 

All works fine. But if I add types to my allRoutes for some typecheking like this:

const allRoutes: {[key: string]:string} = {
  routeHome: '',
  routePortfolio: 'portfolio'
};

or like this:

interface IRoutes {
    [key: string]: string;
}

const allRoutes: IRoutes = {
    routeHome: '',
    routePortfolio: 'portfolio'
};

Everything breaks down

I try this in WebStorm or VSCode. If I add a type for object properties - autocomplete stops working. Why does it happen? And how I can fix this?

like image 658
Denis Savenko Avatar asked Sep 03 '18 09:09

Denis Savenko


4 Answers

Once you initialize the constant with type { [key: string]: string }, the original type is lost. If you want to preserve the original type but check that it is assignable to { [key: string]: string }, you can do this:

function asStrings<T extends { [key: string]: string }>(arg: T): T {
  return arg;
}

const allRoutes = asStrings({
  routeHome: '',
  routePortfolio: 'portfolio'
});

There is a suggestion for a solution that would not require calling a function.

like image 73
Matt McCutchen Avatar answered Nov 05 '22 15:11

Matt McCutchen


This is what helped me to have autocompletion and prevent typescript from moaning

type TPage = {
    id: string;
    title: string;
    path: string;
};

function asRecord<T extends Record<string, TPage>>(arg: T): T & Record<string, TPage> {
    return arg;
}

const EXAMPLES_PAGES = asRecord({
    chart2D_basicCharts_BandSeriesChart: {
        id: "chart2D_basicCharts_BandSeriesChart",
        title: "BandSeriesChart",
        path: "/chart2D_basicCharts_BandSeriesChart"
    },
    chart2D_basicCharts_FanChart: {
        id: "chart2D_basicCharts_FanChart",
        title: "FanChart",
        path: "/chart2D_basicCharts_FanChart"
    }
})

const currentExampleKey = Object.keys(EXAMPLES_PAGES).find(key => EXAMPLES_PAGES[key].path === location.pathname);
like image 22
Michael Klishevich Avatar answered Oct 21 '22 06:10

Michael Klishevich


If you want to type your object without autocomplete loss and keep advantage of readonly you can use as const

const object = {
  title: "Autocomplete",
} as const
like image 4
Ion Moraru Avatar answered Nov 05 '22 14:11

Ion Moraru


Logged as WEB-34642, please follow it for updates

like image 3
lena Avatar answered Nov 05 '22 14:11

lena