TypeScript error

TS4111: Dot access to an index signature

  • Error TS4111
  • Reported with noPropertyAccessFromIndexSignature
  • Tested with TypeScript 5.9

An index signature ({ [name: string]: string }, or Record<string, string>) allows any property name, so env.HOEM is as valid as env.HOME. noPropertyAccessFromIndexSignature makes the difference visible: properties the type declares by name are read with a dot, and the others must use brackets.

The rule changes nothing at run time. Its point is that bracket access marks a name the checker cannot verify, so a typo in a dotted name is never hidden behind an index signature.

At a glance

CodeTS4111
MessageProperty '{0}' comes from an index signature, so it must be accessed with ['{0}'].
TypeScript's categoryerror
Listed underUnknown names and members
Turned on by noPropertyAccessFromIndexSignature
In .js files Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file

The message is TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} is filled in by tsc for each error.

What it looks like

env.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: env.js(6,17): error TS4111: Property 'HOME' comes from an index signature, so it must be accessed with ['HOME']. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. env.js(6,17): error TS4111: Property 'HOME' comes from an index signature, so it must be accessed with ['HOME']. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. env.js(6,17): error TS4111: Property 'HOME' comes from an index signature, so it must be accessed with ['HOME']. checked 21 October 2026
/** @type {{ mode: string, [name: string]: string }} */
const env = { mode: "production", HOME: "/home/ada" };

console.log(env.mode);
console.log(env.HOME);error TS4111: Property 'HOME' comes from an index signature, so it must be accessed with ['HOME'].
Dot access to an index signature, under noPropertyAccessFromIndexSignature.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": [],
    "noPropertyAccessFromIndexSignature": true
  },
  "include": ["**/*.js"]
}

What causes it

  • Reading an environment variable, a header or a dictionary entry with a dot (env.HOME) from a type that only has an index signature for it.

How to fix it

Use bracket access

Write env["HOME"]. Names the type declares, such as mode in the example, keep their dot.

env.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
/** @type {{ mode: string, [name: string]: string }} */
const env = { mode: "production", HOME: "/home/ada" };

console.log(env.mode);
console.log(env["HOME"]);
Bracket access for names the type does not declare.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": [],
    "noPropertyAccessFromIndexSignature": true
  },
  "include": ["**/*.js"]
}

Or declare the property

If the name is always there, add it to the type ({ HOME: string, [name: string]: string }); then the dot is fine and a typo in it is an error.

Gotchas

  • process.env is typed with an index signature in @types/node, so process.env.PORT is TS4111 under this option; the environment variables recipe covers it.

Sources

Last reviewed 21 October 2026.