有没有办法分解功能参数并保留对该参数的命名引用?

dwj*_*ton 5 javascript destructuring typescript reactjs

在反应无状态功能组件时,我们通常会这样写:

export function MyCompoment({
    title, 
    foo, 
    bar
}) {
    return <div> title: {title}, ...</div>
}
Run Code Online (Sandbox Code Playgroud)

我们立即将props对象分解为它的变量。

现在,我正在使用Material-UI makeStyles挂钩,并且还在使用TypeScript,而我当前使用它的方式如下所示。

const useStyles = makeStyles((theme : Theme ) =>({
     root: ({foo} : MyComponentProps) => ({
         content: foo
     })
}); 

interface MyComponentProps  {
    title: string; 
    foo: string; 
    bar: string; 
}
export function MyCompoment({
    title, 
    foo, 
    bar
} : MyComponentProps) {
    const classes = useStyles({
        title,
        foo, 
        bar
    }); 
    return <div> title: {title}, ...</div>
}
Run Code Online (Sandbox Code Playgroud)

您会看到问题-我必须重复props变量名称才能传递到类中。

我认为可以避免这种情况的最好方法就是这样写:

export function MyCompoment(props: MyComponentProps) {
    const {
       title, 
       foo, 
       bar
    }  = props; 
    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}
Run Code Online (Sandbox Code Playgroud)

但这比我想要的要麻烦一些。

我想知道是否可以做类似的事情:

export function MyCompoment({
       title, 
       foo, 
       bar
    }  = props : MyComponentProps) {

    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}
Run Code Online (Sandbox Code Playgroud)

我知道我很挑剔,只是想知道。

Nic*_*las 8

没有(大部分)


从语法上看:

很难证明否定,所以我不得不去语法。

据我所知,Typescript 没有提供任何 javascript 没有的额外解构能力,所以我只会为 javascript 回答这个问题。

在 ES6 语法中,单个函数参数无法在一个参数中同时被破坏并在参数列表中指定一个名称。

如果您查看ES6 语法for FormalParameter,它是参数列表中的一个内容,您会发现它只能是 a BindingElement,它可以是 aSingleNameBinding或 a BindingPattern— 不能同时是两者。绑定模式只能进行解构,单名称绑定只能分配一个值,因此无法同时进行。

(请注意,我链接的语法只是某人放在 github 上的要点。我不认为有人会在 github 上发布误导性的 ES6 语法,但如果您持怀疑态度,您可以随时查看不太方便的官方语法。)

可能还有其他一些我错过的疯狂方法可以做到这一点,但我以前从未见过它并且会感到非常惊讶。


如果你真的想...

你是“你能想到的最好的方式”也是我能想到的最好的方式。你应该这样做。

不过,我不喜欢回答“不”,因此如果您真的想将其全部放入参数列表中,您可以做一些令人不快的事情。如果你这样做:

function assignAndDestructure(props, { foo, bar } = props) {
    // props, foo, and bar will all be assigned
}
Run Code Online (Sandbox Code Playgroud)

哪种符合您的标准。然而,它创建了一个可选的第二个参数,调用者可以滥用它来破坏你的解构。您可以通过将其分配给 Typescript 中没有该参数的类型来隐藏它,但这仍然存在风险。


总之,没有好的方法可以做到,但有一个坏的方法。使用你提到的“你能想到的最好的”。


小智 8

我不明白为什么有人想出这个答案......你总是有一个对参数的引用arguments

function _test({ a, b }){ 
  var arg = arguments[0];
  console.log("a=",a,"b=",b,"arg=",arg);
}
Run Code Online (Sandbox Code Playgroud)

测试时会产生以下输出:

_test({ a:23, b:"asd", c:"$" })
// a= 23 b= asd arg= { a: 23, b: 'asd', c: '$' }
Run Code Online (Sandbox Code Playgroud)

在你的情况下,可以这样做。

export function MyCompoment({
       title, 
       foo, 
       bar
    }) {
    const props = arguments[0];
    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案。`arguments` 是您正在寻找的参考。**但是**它不应用任何默认值,“参数”将准确包含调用该函数所用的数据。因此,最好接受单个参数,然后再对其进行解构。 (2认同)