TypeScript @type {const} produces namespace in .d.ts instead of normal object type

p4rjhz4m  于 7个月前  发布在  TypeScript
关注(0)|答案(6)|浏览(69)

🔎 搜索词

@type {const}
const
定义类型

🕗 版本与回归信息

  • 所有版本都存在崩溃问题

⏯ Playground链接

https://www.typescriptlang.org/play?target=99&jsx=0&ts=5.3.2&filetype=ts#code/KYDwDg9gTgLgBAYwgOwM7wLYE8DCL1wC8cA9AFRlwACMWYwcA3kmjAL5xklMCwAUAEgAZhAgAuOAHIARgEMokgDT9hAV1UTGK4aIkz5klW35sA3PyA

💻 代码

// Typescript file
export const myConst = /** @type {const} */ {
	foo: 'bar',
	fuu: {
		foo: 'bar'
	}
};
// Javascript file
export const myConst = /** @type {const} */ {
	foo: 'bar',
	fuu: {
		foo: 'bar'
	}
};

🙁 实际行为

// .D.TS from Typescript file
export declare const myConst: {
    foo: string;
    fuu: {
        foo: string;
    };
};
// .D.TS from Javascript file
export namespace myConst {
    let foo: string;
    namespace fuu {
        let foo_1: string;
        export { foo_1 as foo };
    }
}

🙂 预期行为

两种情况下都有相同的输出。 Typescript文件的输出是正确的。

关于问题的附加信息

  • 无响应*
m1m5dgzv

m1m5dgzv1#

@type {const}似乎无关紧要-无论其是否存在,.js都会产生相同的输出。
请注意,TS在处理.ts文件时会忽略JSDoc注解中的类型信息。

kgqe7b3p

kgqe7b3p2#

从TypeScript文档中:您甚至可以像TypeScript一样进行类型转换,例如:
let one = /** @type {const} */(1);
我想,TypeScript和JavaScript中的相同代码应该输出相同的JavaScript和相同的定义类型文件。甚至更多,当您使用jsdoc编写JavaScript代码时,就像TypeScript支持的那样。

daolsyd0

daolsyd03#

在TS文件中,您需要使用TS语法进行类型注解/Assert。从.ts和.js文件生成相同的.d.ts输出并非预期的不变性。

wvmv3b1j

wvmv3b1j4#

那么,如何注解JS文件以获得常量声明?我试图将库的类型暴露出来,以便使用Typescript进行使用,但这并不是Typescript开发者所期望的const:

export namespace myConst {
    let foo: string;
    namespace fuu {
        let foo_1: string;
        export { foo_1 as foo };
    }
}

另一方面,根据您的回答,如果我想将项目从js迁移到ts,可能会在迁移过程中产生意外的结果。我认为Typescript是Javascript的超集,相同的代码应该产生相同的输出。

vof42yt1

vof42yt15#

这里隐含了两个问题:

  • TS 和 JS .d.ts 输出应该是相同的 - 再次强调,这不是一个不变式
  • JS .d.ts 在生成奇怪的 namespace 声明时,它本可以只是一个 const - 这应该改变
sdnqo3pr

sdnqo3pr6#

我认为有两个较小的重现对是相关的。
等价的 'as const':

export const a_ts = { foo: 'bar' } as const
export const a_js = /** @type {const} */({ foo: 'bar' })

a_ts 和 a_js 都应该具有类型 { readonly foo: 'bar' },而不是 { foo: string }。快速信息显示它们确实如此,因此这里没有错误。
等价的 const 对象字面量:

export const b_ts = { foo: 'bar' }
export const b_js = { foo: 'bar' }

b_ts 和 b_js 都应该生成 export declare const b_ts: { foo: string },但 b_js 生成的是

export namespace b_js {
  let foo: string
}

这是错误;较长示例中的其余 export { foo_1 as foo } 是命名空间所需的重命名技巧(就我所知)。
我确信这是由于 const x = { object: "literal" } 被标记为赋值声明,因此修复可能是绑定器的设计更改或声明发出的解决方法(其中解决方法基本上是“这看起来很特殊,但只有一个声明,所以最后还是要正常处理”。

相关问题