使用TypeScript与OLOO模式时,类型化This后调用init函数报错的解决方法
解决TypeScript OLOO模式下this类型绑定问题
问题根源在于你直接调用Autocomplete.init()时,this指向的是Autocomplete对象本身,但这个对象初始状态下并没有input、url等属性,不符合你定义的类型要求,所以TypeScript报错。OLOO模式的核心是通过原型继承创建实例,而非直接操作原原型对象,正确的做法如下:
步骤1:调整类型定义
先定义完整的实例接口,再把原型对象的类型设为“缺少实例属性的接口”,明确原型只提供方法:
// 定义实例应具备的所有属性和方法 interface AutocompleteInstance { input: HTMLInputElement; url: string; listUI: HTMLElement; overlay: HTMLElement; wrapInput: () => void; createUI: () => void; init: () => void; } // 原型对象只包含方法,不包含实例属性 const Autocomplete: Omit<AutocompleteInstance, 'input' | 'url' | 'listUI' | 'overlay'> = { wrapInput: function (this: AutocompleteInstance) { let wrapper = document.createElement("div"); wrapper.classList.add("autocomplete-wrapper"); this.input.parentNode?.appendChild(wrapper); wrapper.appendChild(this.input); }, createUI: function (this: AutocompleteInstance) { let listUI = document.createElement("ul"); listUI.classList.add("autocomplete-ui"); this.input.parentNode?.appendChild(listUI); this.listUI = listUI; let overlay = document.createElement("div"); overlay.classList.add("autocomplete-overlay"); overlay.style.width = `${this.input.clientWidth}px`; this.input.parentNode?.appendChild(overlay); this.overlay = overlay; }, init: function (this: AutocompleteInstance) { this.input = document.querySelector("input") as HTMLInputElement; this.url = "/countries?matching="; this.wrapInput(); this.createUI(); }, };
步骤2:通过原型创建实例并初始化
使用Object.create()基于原型对象创建新实例,再调用init方法,此时this指向新实例,初始化的属性会挂载在实例上,完全符合类型要求:
document.addEventListener("DOMContentLoaded", () => { const autocompleteInstance = Object.create(Autocomplete) as AutocompleteInstance; autocompleteInstance.init(); });
为什么这样可行?
OLOO模式的本质是让实例对象链接到原型对象继承方法,而实例自身存储状态属性。通过Object.create()创建的实例会继承Autocomplete的所有方法,init方法执行时会给实例添加input、url等属性,完美匹配AutocompleteInstance接口的定义,TypeScript不会再报错。
内容的提问来源于stack exchange,提问作者SrdjaNo1
相关产品推荐
相关产品推荐

