我目前正在将JavaScript代码库重写为Typescript。我发现函数中的数据定义如下:MyProps:
.v-calendar-daily_head-day-label {
display: none;
}
用法一直是这样的:
interface MyProps {
type: string;
foo?: unknown;
bar?: unknown;
someCommonProps: unknown;
}
通过进一步的研究,我发现可以更精确地定义接口/类型,如下所示:
const myFunction = (props: MyProps) => {
const { type, foo, bar, someCommonProps } = props;
if (foo) {
//Do something
}
if (bar) {
//Do something else
}
};
但是通过将新的MyProps分配给props,我将在myFunction的第一行得到一个错误:属性'foo'在类型'MyProps'上不存在。与“酒吧”类似。不用重写可能会引入错误的最佳方法是什么?
答案 0 :(得分:1)
对于类,您可以这样操作:
class Foo {
type: 'a' | 'b' | 'c';
foo: unknown;
}
class Bar {
type: 'd' | 'e' | 'f';
bar: unknown;
}
type FooBar = Foo | Bar;
type MyProps = FooBar & {
someCommonProps: unknown;
};
const myFunction = (props: MyProps) => {
if (props instanceof Foo) {
// Do something
console.log(props.someCommonProps);
}
if (props instanceof Bar) {
// Do something else
}
};
答案 1 :(得分:1)
如果您的标签是字符串联合,则可以使用switch(props.type)
并枚举所有情况下的值:
const myFunction = (props: MyProps) => {
switch (props.type) {
case 'a': case 'b': case 'c':
let x = props.foo;
break;
case 'd': case 'e': case 'f':
let y = props.bar;
break;
}
};
从长远来看,这可能很乏味,这是一种自动化的方法:
let FooTag = ['a', 'b', 'c'] as const;
interface Foo2 {
type: typeof FooTag[number];
foo: unknown;
}
function isFoo2(x: Foo2 | Bar2): x is Foo2 {
return (FooTag as readonly string[]).indexOf(x.type) >= 0;
}
...
const myFunction2 = (props: MyProps2) => {
if (isFoo2(props)) {
let x = props.foo;
}
if (isBar2(props)) {
let x = props.bar;
}
答案 2 :(得分:0)
虽然不那么优雅,但我认为这是实现此目的的最简单方法:
interface Foo {
type: "a" | "b" | "c";
foo: unknown;
}
interface Bar {
type: "d" | "e" | "f";
bar: unknown;
}
type FooBar = Foo|Bar;
type MyProps = FooBar & {
someCommonProps: unknown;
}
还要考虑是否可以执行以下操作:
const myFunction = (props: MyProps) => {
const { type, someCommonProps } = props;
const foo = 'foo' in props ? props.foo : undefined;
const bar = 'bar' in props ? props.bar : undefined;
if (foo) {
//Do something
}
if (bar) {
//Do something else
}
};