flow icon indicating copy to clipboard operation
flow copied to clipboard

How to tell flow that a dynamic string is just like a normal string

Open buschco opened this issue 10 months ago • 2 comments

type Props = $ReadOnly<{
    actionId: string,
    onPress: (args:{dispatch: () => void}) => void
}> | $ReadOnly<{
    actionId?:void,
    onPress: () => void
}>

const A: (p:Props) => void = () => {}

const actionId: string = `1`

A({
    actionId,
    onPress:({dispatch}) => {dispatch()}
           // ^ property `dispatch` is missing in undefined [1]. [incompatible-use]
})

A({
    actionId: ''.concat(''),
    onPress:({dispatch}) => {dispatch()}
           // ^ property `dispatch` is missing in undefined [1]. [incompatible-use]
})

A({
    actionId: '1',
    onPress:({dispatch}) => {dispatch()}
    // no error like it should be
})

Flow version: 0.259.1

Expected behavior

No error.

Actual behavior

Flow treats "dynamic" strings in a different way.

  • Link to Try-Flow or Github repo:

https://flow.org/try/#1N4Igxg9gdgZglgcxALlAIwIZoKYBsD6uEEAztvhgE6UYCe+JADpdhgCYowa5kA0I2KAFcAtiRQAXSkOz9sADwxgJ+NPTbYuQ3BMnTZA+Y2yU4IwRO4A6SFBIrGVDGM7c+h46fNRLuKxJIGWh8MeT0ZfhYlCStpHzNsFBAMIQkIEQwJODAQfiEyfBE4eWw2fDgofDBMsAALfAA3KjgsXGxxZC4eAw0G-GhcWn9aY3wWZldu-g1mbGqJUoBaCRHEzrcDEgBrbAk62kXhXFxJ923d-cPRHEpTgyEoMDaqZdW7vKgoOfaSKgOKpqmDA+d4gB5fMA-P6LCCMLLQbiLOoYCqgh6-GDYRYIXYLSgkRZkCR4jpddwPfJLZjpOBkO4AX34kA0SRWxgABAAFSiwkjsgC87IAJAAlVhsADyUEGAB5gAAdKDs5Xs6JwaAASTYyHZ9lMUAQvEVKvZ0G5Px1AAoqAgSKg2LTHHtalaAJQCgB87IaEDgbHp7v5Xp9fsV9K9AB9hWL2FLZQqlSq1Zq2AB+ZAhthGxPKs0sEh29mWwPB31sMMexWK2z2dkAQStjGQ3N5Je9ZYFRbbwHpVce0FryagWp1eoqCE7AAMAIyTvt1y0Jk1DrXZk15i2Lh1MGq1AOe9nAbdOurF3tQAPzxfGpPKdXD7XsgDkT5s0HmlpfrrXKo3BeQW6Oru+5Boex67meYauleS63vCD46k+05Pj+uZQOa-6ATuzogV6R5Ac6kEXq6uQgA0JgkPeSQNAADFYABMACsACcVjTiA9JAA

buschco avatar Feb 03 '25 15:02 buschco

This is a result of our contextual typing heuristics. For now, we only use specific syntactic patterns (e.g. only literal) to help pick one of the disjoint union.

There might be something we can do better here, since TS is able to do that.

SamChou19815 avatar Feb 03 '25 18:02 SamChou19815

A workaround could be setting the prop twice:

e.g.

A({
    actionId: '',
    actionId: ''.concat(''),
    onPress:({dispatch}) => {dispatch()}
})

https://flow.org/try/#1N4Igxg9gdgZglgcxALlAIwIZoKYBsD6uEEAztvhgE6UYCe+JADpdhgCYowa5kA0I2KAFcAtiRQAXSkOz9sADwxgJ+NPTbYuQ3BMnTZA+Y2yU4IwRO4A6SFBIrGVDGM7c+h46fNRLuKxJIGWh8MeT0ZfhYlCStpHzNsFBAMIQkIEQwJODAQfiEyfBE4eWw2fDgofDBMsAALfAA3KjgsXGxxZC4eAw0G-GhcWn9aY3wWZldu-g1mbGqJUoBaCRHEzrcDEgBrbAk62kXhXFxJ923d-cPRHEpTgyEoMDaqZdW7vKgoOfaSKgOKpqmDA+d4gB5fMA-P6LCCMLLQbiLOoYCqgh6-GDYRYIXYLSgkRZkCR4jpddwPfJLZjpOBkO4AX34kA0SRWxgABAAFSiwkjsgC87IAJAAlVhsADyUEGAB5gAAdKDs5Xs6JwaAASTYyHZ9lMUAQvEVKvZ0G5Px1AAoqAgSKg2LTHHtalaAJQCgB87IaEDgbHp7v5Xp9fsV9K9AB9hWL2FLZQqlSq1Zq2AB+ZAhthGxPKs0sEh29mWwPB31sMMexWK2z2dkAQStjGQ3N5Je9ZYFRbbwHpVce0FryagWp1eoqCE7AAMAIyTvt1y0Jk1DkfsgDka+zy+U6uHWeNKrzFsXDqYNVqAc97OAp6ddWLvagAfni4PypX2vXm7fqp3KZ1G42NA8yWhurpboeUDmgWyAno656XkG163ueD5hq6L5Lkmf57gB07fjmppQfmdpwWezqIV6N7wc6aFPq6uQgA0JgkLuSQNAADFYABMABsADMVgcSA9JAA

buschco avatar Mar 10 '25 14:03 buschco