日期:
来源:全栈修仙之路收集编辑:Qiuyi
证明即程序,结论公式即程序类型。
—— 柯里-霍华德对应[1]
背景
我们每天的编码都会使用到类型系统,本篇文章希望能够简单地介绍原理到实践,让读者能更好的使用类型系统编写出类型安全并简洁的代码。
本篇文章预期读者是拥有 TypeScript 基础的同学。
CodeShare - 安全的 any 互操作
众所周知,any
是一个危险的类型,可以关闭所有类型检查。但是实际的浏览器程序中不可能完全避免 any
类型进入类型系统,对我们的类型推理产生影响。比如
JSON.parse()[2] Reflect.get()[3] Response.json()[4]
对于 any
的处理,最佳方法是先把他变成 TypeScript 的顶层类型 unknown
,这样它就不能在类型系统中随意传播了,必须要求程序员主动进行类型转换才能在其他地方使用。
分享一个代码片段,这个代码片段尝试将 window 上的挂载的一个全局方法获取出来,假如存在,就转换成安全的类型后再放出去;假如不存在,就换成一段 fallback 逻辑并展示警告信息。
export type I18NMethod = (key: string, options: unknown, fallbackText: string) => string;
function isI18nFunction(input: unknown): input is I18NMethod {
return typeof input === 'function';
}
function makeI18nMethod(): I18NMethod {
let hasWarnShown = false;
return function (key: string, options: unknown, fallbackText: string) {
if (Reflect.has(window, '$i18n')) {
// $i18n是一个挂载到 window 对象上的全局方法
const globalI18n: unknown = Reflect.get(window, '$i18n');
if (isI18nFunction(globalI18n)) {
return globalI18n(key, options, fallbackText);
}
}
showWarnOnce();
return fallbackText;
};
function showWarnOnce() {
if (hasWarnShown === false) {
hasWarnShown = true; // 只展示一次警告
console.warn('Cannot Fetch i18n Text: window.$18n is not a valid function');
}
}
}
export const $i18n = makeI18nMethod();
// usecase
$i18n("hello-text-key", {}, "你好");
13 行获取了一个 any 类型的对象,第一步是将其转换为 unknown 类型。
假如 14 行不调用 isI18nFunction
转换类型,而是直接返回 globalI18n
,ts 将报错:Type 'unknown' is not assignable to type 'string'
,从而要求开发者必须编写类型转换。