JSDoc 中的类型断言函数

Type asserting function in JSDoc

我正在尝试提出以下 TypeScript 类型断言函数的 JavaScript+JSDoc 变体:

function typeCheck<T>(value: unknown, type: new () => T) {
    if (value instanceof type) {
        return value;
    }

    throw new Error('Invalid type');
}

const maybeButton: unknown = document.createElement('button');
const button = typeCheck(maybeButton, HTMLButtonElement);

我想到了这个,但我收到一个错误:

/** @template T */
/** @returns {T} */
export default function check(/** @type {unknown} */ object, /** @type {new () => T} */ type) {
  if (object instanceof type) {
    /** @type {any} */
    const any = object;

    /** @type {T} */
    const t = any;

    return t;
  }

  throw new Error(`Object ${object} does not have the right type '${type}'!`)
}

错误在调用站点:const button = check(event.currentTarget, HTMLButtonElement);HTMLButtonElement 带有下划线,错误消息显示:

Argument of type '{ new (): HTMLButtonElement; prototype: HTMLButtonElement; }' is not assignable to parameter of type 'new () => T'.
  Type 'HTMLButtonElement' is not assignable to type 'T'.
    'T' could be instantiated with an arbitrary type which could be unrelated to 'HTMLButtonElement'.ts(2345)

是否可以开发这样的 JSDoc 函数,当传递一个 unknown 时,将仅使用 TypeScript 类型干扰和逃逸分析来验证和 return 未知对象键入为提供的类型?

我一般对 JSDoc 不感兴趣,但特别是在 Visual Studio 代码中使用的 JSDoc 使用 TypeScript 语言服务在 JavaScript 项目上使用 JSDoc 进行类型提示。

TypeScript Discord 上有人帮我想出了答案:

/**
 * @template T
 * @returns {T}
 * @param {unknown} obj
 * @param {new () => T} type
 */
export default function assertInstance(obj, type) {
  if (obj instanceof type) {
    /** @type {any} */
    const any = obj;

    /** @type {T} */
    const t = any;

    return t;
  }

  throw new Error(`Object ${obj} does not have the right type '${type}'!`)
}

Assertion Functions introduced in TS 3.7 可以在其调用范围内断言值的类型。

/**
 * @param {*} maybeString
 * @returns {asserts maybeString is string}
 */
function assertString(maybeString) {
  if (typeof maybeString !== 'string') throw Error('not a string');
}

/**
 * @param {unknown} something
 */
function demo(something) {
  something.concat; // type error
  assertString(something);
  something.concat; // valid
}