-
Notifications
You must be signed in to change notification settings - Fork 63
Conversation
f8a8e3b
to
3710d31
Compare
function checkHref(p: typeof props): p is { href: string } { | ||
return typeof p.href === 'string' && !['', '#'].includes(p.href) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks curious to me 😯 Is p is { href: string }
the returning type or an extension of the params type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a type assertion: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-type-assertions
Basically TypeScript will see this and know that any code that comes after a call to this function that uses it as a condition, that the passed in valid is { href: string }
(notably here without the ?
on the property making it optional).
// Out here `props.href` is `undefined | string` because `href` is an optional prop
if (checkHref(props)) {
// in here `props.href` is no long optional, it's "proven" to be an actual string and not undefined by `checkHref`
}
// out here it is optional again because we're outside the conditional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense for the part of the code using the checkHref
function but my doubt is actually with the definition highlighted here 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, sorry.
The p is { href: string }
is the return type yes. Any return type with the is
form is taken to be a predicate and the return value is interpreted as a boolean
. It refines the type whatever the caller passes for p
at the call site.
With this definition the only part we can encode in the return type is the typeof p.href === 'string'
(essentially all that is being said in the return predicate). We could add the second check against the empty string and '#'
but TypeScript just throws it away when you actually reference href
after the check: https://www.typescriptlang.org/play?#code/C4TwDgpgBACgTgezAZygXigbygCzhAMwH4AuKZYOASwDsBzKAXwChmCBXGgY2CoRqhccELgGsAEvgIAKMGXhJkASjJgoVVNjyEyAUQAeXADbsAJhAA8FavQA0UAOQOoAH0cBiBwD4mWZlCh8YHY4ATAAOm0CdDQMB2taOmcAMmSoAEIAbSd7B08AXXDaYzMIZFlIqSVmFmYufgooMEQUdCxaqmjpIREJKVkW5SU-AObFAG5-KAB6aagAPSIpzqgBxUrCGLiHYcwpgIDZg4DFqZYWIA
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the explanation!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I see! Thank you for this explanation, the example in the link made it crystal clear. The way Typescript works is interesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great.
3710d31
to
ddf02e0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested using the instructions, works as you describe. LGTM!
function checkHref(p: typeof props): p is { href: string } { | ||
return typeof p.href === 'string' && !['', '#'].includes(p.href) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the explanation!
Description
In the Vue SFC typescript PR #1163 I added the
types
compiler option to our tsconfig and this removed some critical nuxt types from global scope. Adding them back also revealed that I'd accidentally duplicated the work that the Nuxt vue-i18n module does to make the types work so I was able to remove some code as well.I also added an ESLint rule to prevent accidentally destructuring the
i18n
object as it will result in a failure if you do and try to call one of the methods destructured due to the dependency onthis
in the method.Testing Instructions
Go to
use-i18n.ts
and call the function, make sure it has the correct types when you inspect the type information in your editor (try to use some of the properties like.t
for example). This tests the removal of the code in the nuxt__types/index.d.ts module and also tests that the types from the module are being added.Checklist
Update index.md
).main
) or a parent feature branch.Developer Certificate of Origin
Developer Certificate of Origin