我也遇到了类似的问题,我尝试写一个i18n.t函数,支持t('xxx')调用,支持t.xxx直接取值,支持txxx
标签函数调用,同时不希望原型链上任何方法或属性干扰typescript的类型推导列表。我查阅了社区的一些问题,这是我的解决方案。
const Message = <const>{__proto__: null, site_name: 'my site name', more: 'More Q&A' }
declare abstract class NonPrototype extends null {
private apply(): never
private bind(): never
private call(): never
private arguments: never
private caller: never
private length: never
private name: never
private prototype: never
private hasOwnProperty: never
private isPrototypeOf: never
private propertyIsEnumerable: never
private toLocaleString: never
private valueOf: never
private ['constructor']: never
}
interface Translate extends Message, NonPrototype {
<const K extends keyof Message>(key: K): Message[K]
(key: TemplateStringsArray): string
}
export const t: Translate = (k => messages[k]) as any
window.t = t
Reflect.setPrototypeOf(t, messages)
Reflect.deleteProperty(t, 'length')
Reflect.deleteProperty(t, 'name')
t.site_name // my site name
t.more // More Q&A
t.unknown_key // error
t('site_name') // my site name
t('more') // More Q&A
t('unknown_key') // error
var key: string = 'site_name'
var value = t[key] // any
t.apply // error
t.bind // error
t.toString // error
t.hasOwnProperty // error
t.constructor // error
t.__proto__ // error
t[Symbol.iterator] // any
new t // error
/**
* ## try read property, the type list is
* Symbol
* site_name
* more
*
* ## first item is Symbol, i can’t remove it 😡
*/
// t.
/**
* ## try call translate function, the list is
* site_name
* more
*
* ## there is no any other property 🥰
*/
// t('')