您的功能请求是否与问题有关?
由于打字稿的控制流分析,以下代码会出现打字稿错误。
但这对于选择包装器组件非常有用。
<script lang="typescript">
export let value: string | number = '';
if (typeof value === 'number') {
console.log(value.toFixed())
}
</script>
<select bind:value={value}></select>
描述您想要的解决方案
在svelte2tsx
中, props
和响应式语句$: { }
需要从控制流上下文中取出,可能需要用这样的回调包装它:
declare function __sveltets_invalidate<T>(getValue: () => T): T
/*export*/ let value: string | number = __sveltets_invalidate(() => '')
let b: 'A' | 'B' = 'A';
() => {
$: {
console.log(b)
}
}
附加上下文
在此处添加有关功能请求的任何其他上下文或屏幕截图。
使用 invalidate-wrapper 围绕道具的好主意。 也许我们甚至不需要为响应式语句添加另一个包装器? 或者在任何情况下这会引发控制流错误?
将export let
更改为let
并将语句包装在$: {}
将有相同的错误
<script lang="typescript">
let value: string | number = '';
$: {
if (typeof value === 'number') {
console.log(value.toFixed())
}
}
</script>
如果值被事件处理程序重新分配。 它的类型可能会改变
啊,没想到。 谢谢!
道具的回调函数不起作用大声笑。 需要另寻出路。
顺便说一句,如果我们将第一个 $: 标签更改为 let ,就像我们之前在整个策略线程中讨论的那样,这种包装可以在 $: 变量中使用。 因为它的类型取决于另一个let
。 所以它会起作用。
另一个问题,这个union类型的props在导出的prop def中也会有一个字符串类型,因为同样的原因
export let someProps : string | number = ''
到
declare function __sveltets__invalidateWithDefault<T>(getValue: () => T | undefined): T;
let someProps: string | number = ''
someProps = __sveltets__invalidateWithDefault(() => someProps);
这行得通,但有点hacky
export let test: string | number = '' as any;
作品
@PatrickG的解决方案更好。 但是这两种方法都会使道具具有未定义的类型。
export let test: string | number | undefined = '' as any;
test // test is shouldn't be undefined here
你能以某种方式从 typescript AST 中获取类型并使用它来构造它吗? 或者使用某种 AST 遍历/正则表达式来获取类型定义(在:
之后和=
之前的所有内容),然后将其放在它后面: export let test: string | number = '' as string | number
。
@PatrickG的解决方案更好。 但是这两种方法都会使道具具有未定义的类型。
export let test: string | number | undefined = '' as any; test // test is shouldn't be undefined here
对我来说测试是string | number
。 不是undefined
。
游乐场示例
如果strictNullChecks
被启用,它将是undefined
( strict: true
也启用它)
游乐场示例
如果strictNullChecks
被启用,它将是undefined
(strict: true
也启用它)
然后它将是string | number | undefined
。 问题出在哪里?
因为当您的默认值不是undefined
$ 时,它不能是undefined
#$ 。 我想消除undefined
类型,以便用户不必进行不必要的空检查来抑制undefined
错误。
如果您将| undefined
添加到类型,当然它可以是未定义的,并且您应该在尝试调用方法时检查它是否未定义。
<!-- Component.svelte -->
<script lang="ts">
export let test: string | undefined = '' as any; // `string | undefined` means it can be undefined.
test.toUpperCase(); // not safe - because `test` can be `undefined`
test?.toUpperCase(); // safe
</script>
<!-- Other component -->
<script>
import Component from './Component.svelte';
</script>
<Componen test={undefined} />
我目前看到的唯一问题是,如果它有一个初始值,svelte 扩展应该使 prop 成为可选的。
我认为我们可以在这里使用VariableDeclaration.initializer而不是在此处检查类型中的undefined
因为 svelte 编译器将其编译为
let { test = '' } = $$props
所以 test 不能是undefined
即使你明确地传递 undefined 作为道具。 如果您稍后将其重新分配给undefined
,它只能是未定义的。
也许做我打算做的事情太复杂或不可能。 它可能只是一个很少有人会使用的边缘案例。
如果您传递一个更改为未定义的变量,它仍然可以是未定义的。
https://svelte.dev/repl/hello-world?version=3.23.2
那么它的反应性声明可能是undefined
? 也许我们应该只做响应式并要求用户显式转换默认值的类型。
export let a: string | number | undefined = '' as string | number
铸造可以工作。 但是在js中它不会在函数中有未定义的类型
/**<strong i="8">@type</strong> { string | number | undefined }*/
let name = /**<strong i="9">@type</strong> {string | number} */ ("world"),
world = '';
name
function a() {
name
}
我认为我们可以在这里使用 VariableDeclaration.initializer 而不是在这里检查类型中的 undefined
好点子! 它可以区分可选的道具和可能未定义的
这就是我的意思,带有可选道具: https ://github.com/PatrickG/language-tools/commit/c5f00f75df74c8e3dcfc9842dad4256b9d4f29f2
并且在初始化器后面加上as any
,vscode 不再认为export let test: string | number = '';
是一个字符串。 https://github.com/PatrickG/language-tools/commit/7f630bbf7d66a037590384d3e2a7f8b7314b622c
我可以用我的更改创建 PR 吗?
我觉得第一个还行!
as any
的另一个缺点是它不会进行类型检查。 因此,也许它需要转换为用户定义的任何内容。
let a: string | number = true as any;
另外,需要通过 js 中的jsdoc
来进行强制转换。 我今天试过了。
关于未定义的问题,我放弃了。 因为我们找不到可以解决问题的通用函数。 我们只能手动检查其初始化程序是否未定义,但不能手动检查作为初始化程序传入的变量是否未定义。 假阴性似乎更重要。
我觉得第一个还行!
as any
的另一个缺点是它不会进行类型检查。 因此,也许它需要转换为用户定义的任何内容。let a: string | number = true as any;
啊对。
那这个呢:
declare function __sveltets_initialize<T>(value: T): any;
let test: string | number = __sveltets_initialize<string | number>('');
test; // string | number
let test: string | number = __sveltets_initialize<string | number>(true); // error because `true` is not `string` or `number`
另外,需要通过 js 中的
jsdoc
来进行强制转换。 我今天试过了。
我还没有研究过 jsdoc 的东西
更新:还有另一种方法可以做到as any
export let a: number | string = '1',
b = a;
到
declare function __sveltets_any(dummy: any): any;
let a: number | string = '1'
a = __sveltets_any(a);
let b = a;
不需要类型断言,并且初始化程序得到了类型检查。 这样会显示输入错误:
export let a: ISomeInterface = {};
export let b: string | number = true;
我也想过重新分配,但想阻止它,因为我认为它更难做^^
你实施这个吗?
@jasonlyu123问题是您的 PR 解决的所有问题吗? (询问我是否可以关闭这个)
是的。 谢谢