網站搜尋

Visual Studio Code - 為什麼在 TypeScript 中帶有類型的物件中自動完成停止工作?


我有一個路線列表在一個物件中,想在其他檔案中匯入它,並對物件屬性使用自動完成。

index.ts

import allRoutes from './routes';

allRoutes.routeHome;

routes.ts

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

export default allRoutes; 

一切運作正常。但如果我為我的 allRoutes 添加類型以進行一些類型檢查,如下所示:

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

或者像這樣:

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

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

一切都會崩解

我在 WebStorm 或 VSCode 中嘗試這個。如果我為對象屬性添加類型,則自動完成就停止工作。為什麼會這樣?我該如何解決這個問題?

答案#1

一旦你用類型 { [key: string]: string } 初始化常數,原始類型就會丟失。如果你想保留原始類型但檢查它是否可以指派給 { [key: string]: string },你可以這樣做:

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

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

有一個建議的解決方案,不需要呼叫函數。

答案#2

2024 最新:satisfies 精確解決這個問題

取代:

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

你應該做:

const allRoutes = {
  routeHome: '',
  routePortfolio: 'portfolio'
} as const satisfies Record<string, string>

這將保持物件的自然類型,同時確保它「符合」所提供的類型。

說明

// let's take a more complex type for demonstration
type Route = { path: string, orientation?: 'portrait' |'landscape' }

const routes = {
   home: { path: 'home' }, // ✅
   videoPlayer: { path: 'player', orientation: 'portrait' }, // ✅
   settingsPage: { 
     path: 'settings', 
     orientation: 'randomString', // ❌ Error
     notExisting: false // ❌ Error
   },
} as const satisfies Record<string, Route>

routes.home.path // typed as 'home'
routes.videoPlayer.orientation // typed as "portrait"
  • as const 使物件唯讀,因此在此例子中,它會將 routes.home.path 的類型設定為 "home"
  • satisfies Record<string, Route> 限制類型而不覆蓋它

Typescript 遊樂場

如果你需要覆蓋值類型,則使用更複雜的方式