{"record":{"id":"5d8174ba35ba5cbc","repo":"angular/components","slug":"listkeymanager-items-in-typeahead-mode-must-implem","errorCode":null,"errorMessage":"ListKeyManager items in typeahead mode must implement the `getLabel` method.","messagePattern":"ListKeyManager items in typeahead mode must implement the `getLabel` method\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cdk/a11y/key-manager/list-key-manager.ts","lineNumber":148,"sourceCode":"\n  /**\n   * Modifier keys which are allowed to be held down and whose default actions will be prevented\n   * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.\n   */\n  withAllowedModifierKeys(keys: ListKeyManagerModifierKey[]): this {\n    this._allowedModifierKeys = keys;\n    return this;\n  }\n\n  /**\n   * Turns on typeahead mode which allows users to set the active item by typing.\n   * @param debounceInterval Time to wait after the last keystroke before setting the active item.\n   */\n  withTypeAhead(debounceInterval: number = 200): this {\n    if (typeof ngDevMode === 'undefined' || ngDevMode) {\n      const items = this._getItemsArray();\n      if (items.length > 0 && items.some(item => typeof item.getLabel !== 'function')) {\n        throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');\n      }\n    }\n\n    this._typeaheadSubscription.unsubscribe();\n\n    const items = this._getItemsArray();\n    this._typeahead = new Typeahead(items, {\n      debounceInterval: typeof debounceInterval === 'number' ? debounceInterval : undefined,\n      skipPredicate: item => this._skipPredicateFn(item),\n    });\n\n    this._typeaheadSubscription = this._typeahead.selectedItem.subscribe(item => {\n      this.setActiveItem(item);\n    });\n\n    return this;\n  }\n","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/a11y/key-manager/list-key-manager.ts#L130-L166","documentation":"ListKeyManager.withTypeAhead needs to read the text label of each item to match keystrokes; therefore every item in the QueryList must implement getLabel(): string. withTypeAhead throws this dev-mode error if any item lacks a getLabel function (when the list is non-empty).","triggerScenarios":"Calling keyManager.withTypeAhead() where the managed QueryList contains directive/component instances that do not define getLabel(); adding a new item type to the list that was not updated for typeahead; passing a generic ListKeyManager over plain objects.","commonSituations":"Mixing item classes in a listbox/menu; upgrading CDK and enabling typeahead on an existing key manager; implementing a custom option directive modeled after an older API without getLabel.","solutions":["Implement getLabel(): string on every item directive/component managed by the key manager.","Create a shared interface (e.g., interface WithLabel { getLabel(): string }) and have all items implement it.","Remove withTypeAhead() if keyboard typeahead is not needed."],"exampleFix":"// before\nexport class MyOption { constructor(public value: string) {} }\n\n// after\nexport class MyOption { constructor(public value: string) {} }\ngetLabel(): string { return this.value; }","handlingStrategy":"type-guard","validationCode":"interface LabelItem { getLabel(): string; }\nfunction allItemsHaveLabel(items: unknown[]): items is LabelItem[] {\n  return items.every(i => typeof (i as LabelItem).getLabel === 'function');\n}\nif (allItemsHaveLabel(options.toArray())) keyManager.withTypeAhead();","typeGuard":"function implementsGetLabel(item: unknown): item is { getLabel(): string } {\n  return typeof (item as { getLabel?: unknown }).getLabel === 'function';\n}","tryCatchPattern":"try {\n  keyManager.withTypeAhead();\n} catch (e) {\n  if ((e as Error).message.includes('getLabel')) {\n    console.error('Items must implement getLabel for typeahead');\n  } else throw e;\n}","preventionTips":["Define a shared interface with getLabel(): string that every managed item directive implements.","Write a test asserting typeof item.getLabel === 'function' for each item type.","Skip withTypeAhead() when items cannot provide labels."],"tags":["angular","cdk","a11y","keyboard","typeahead","dev-mode-assertion"],"backgroundTag":"missing-interface-method","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}