TypeScript小技巧(二)

创建于:发布于:文集:奇技淫巧

点击查看上一篇

使用using关键字

如数据库、文件等IO相关的API,一般需要在合适的时机将资源释放,经常需要写这样的代码:

try {
    db.xxx();
} catch (e) {
    // handle error
} finally {
    db.close();
}

在这个TC39提案里,引入了一个新的关键字​using​,用于简化这个流程,当然现在还没有什么浏览器支持这个特性,而TypeScript 5.2对这个关键字提供了支持(tsc会把它转换成旧语法)。首先需要有一个暴露​[Symbol.dispose]​方法的对象,然后在一个代码块中使用using代替const初始化这个对象。

function createDb() {
  console.log("Open!")
 
  return {
    fetch: (params: string) => {
      console.log(params)
    },
    [Symbol.dispose]: () => {
      console.log("Close!")
    }
  }
}
 
{
  using db = createDb()
  db.fetch("select * from table")
}

最后当离开作用域时,该对象的​[Symbol.dispose]​方法就会被自动调用了。

它还有个对应的async版本,需要这么写:

function createAsyncDb() {
  console.log("Open!")
 
  return {
    fetch: async (params: string) => {
      console.log(params)
    },
    [Symbol.asyncDispose]: async () => {
      console.log("Close!")
    }
  }
}
 
{
  await using db = createAsyncDb()
  await db.fetch("select * from table")
}

不过我是不认同为了省去一个手动close的操作,引入一个新关键字的,相比之下,Kotlin的use方式我认为更好。

satisfies

有时会遇到一种情况,如果一个属性的类型是和类型,它的字面量默认不会被推断为字面的类型:

type Foo = Record<string, string | number | undefined>
 
const foo: Foo = {
  a: "nice"
}
 
// 这里就会收到类型错误,因为tsc不认为a是字符串类型
// foo.a不被看作string类型,而是string | number | undefined
foo.a.startsWith("n")

如果改写成:

const foo = {
  a: "nice"
} satisfies Foo

就不会再有错误提示了。使用​satisfies​的另一个区别是,它会限制对象初始化后不能拓展属性:

const foo = {
  hello: "nice"
} satisfies Foo
 
 
// 错误
foo.past = 1
 
const bar: Foo = {
  hello: "nice"
}
 
// 没问题
bar.past = 1

同时它还可以和​as const​一起用:

const foo = {
  hello: "nice",
  bar: 3,
} as const satisfies Foo
 
// Cannot assign to 'hello' because it is a read-only property.
foo.hello = 1
EOF
文章有帮助?为我充个
版权声明