2

Like the title says, I'm confused as to what 'as never' means in this piece of code. I read that it's supposed to mean something that never occurs or excludes other types but I'm not quite grasping why it's being used the way it is in the piece of code below.

import { View, Button, Text, StyleSheet, FlatList, TouchableOpacity, Image } from 'react-native'
import React from 'react'
import { useNavigation } from '@react-navigation/native'

const data = [
  {
    id: 1,
    title: 'Google Search',
    screen: 'MapScreen',
  },
  {
    id: 2,
    title: 'I\'m Feeling Lucky',
    screen: 'MapScreen',
  }
]

const NavOptions = (props: NavProps) => {
  const navigation = useNavigation();
  return (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id}
      horizontal
      renderItem={({ item }) => (
        <View style={styles.container}>
          <TouchableOpacity
            onPress={() => props.term && navigation.navigate(item.screen as never, {
              term: props.term,
            } as never)}
            style={styles.button}>
            <Text style={styles.text}>{item.title}</Text>
          </TouchableOpacity>
        </View>
      )}
    />
  )
}

const styles = StyleSheet.create({
  container: {
    padding: 10,
  },
  button: {
    backgroundColor: "#f8f9fa",
    padding: 10,
  },
  text: {
    color: "black",
    textAlign: "center",
  },
});

type NavProps = {
  term: string;
}

export default NavOptions
user3840170
  • 26,597
  • 4
  • 30
  • 62
Amr Shawki
  • 99
  • 8
  • Does this answer your question? [What does the "as" keyword do?](https://stackoverflow.com/questions/55781559/what-does-the-as-keyword-do) – Robert Harvey Apr 25 '22 at 15:16
  • From the link above: *"The `as` keyword is a Type Assertion in TypeScript which tells the compiler to consider the object as another type than the type the compiler infers the object to be."* – Robert Harvey Apr 25 '22 at 15:17
  • @RobertHarvey no I understand that 'as' is for type assertion in typescript. What I don't understand is why we put 'as never' in the piece of code above. – Amr Shawki Apr 25 '22 at 15:18
  • It looks like nonsense. This code is wrong. – user3840170 Apr 25 '22 at 15:19
  • I believe this cannot ever be right, and looks like a mistake. Maybe because someone could not get the type right and used `never` instead of `any`, for undecipherable reasons. – Mathieu Apr 25 '22 at 15:23
  • @Mathieu This code is from a project that handles navigation. When I run the project in vscode, everything works and I don't get an errors from Typescript or in the functionality and I can't understand why haha – Amr Shawki Apr 25 '22 at 15:25
  • Please post the full source, or wider context, then. I cannot understand this typing either. I assume `useNavigation` is from this library https://reactnavigation.org/docs/navigation-prop#navigate. `as` is used to coerce a type against TS's assumptions, and there is no reason I can find in this context. – Mathieu Apr 25 '22 at 15:29
  • @Mathieu I think this is answerable as it is already. No need to post full code. – user3840170 Apr 25 '22 at 15:31
  • @Mathieu I just edited and added the full source code. This is supposed to be a component that generates the google buttons and navigate to the proper screen – Amr Shawki Apr 25 '22 at 15:31
  • 2
    There is still no reason for the use of `as never` that I can see, and they can / should probably be deleted – Mathieu Apr 25 '22 at 15:33

1 Answers1

4

The code is simply wrong.

Your understanding of never is roughly correct: it is a type with no valid values and it often arises as intersection of incompatible types; it represents unreachable code, situations that are logically impossible and expressions that cannot be fully evaluated. A typical example is functions that throw instead of returning normally:

function raiseRangeErr(e: string): never {
    throw new RangeError(e);
}

function div(a: number, b: number): number {
    return b !== 0 ? a / b : raiseRangeErr("division by zero");
}

never has the unique property that expressions of this type are assignable to any other type. This works, because since never has no values, in particular it has no values that may fail to be members of the target type.

The programmer who wrote that code probably wanted to lazily take advantage of this property to suppress errors about unassignable types. From a type theory perspective, this is incorrect: code which has never in scope is supposed to be unreachable, yet the code in the question is clearly anything but.

Type assertions are best avoided anyway; if you can simply remove those assertions and not get any errors, do that. If you have to use a type assertion after all, use a type specific to the situation at hand. In the worst case, use as any. The only situation in which as never would be remotely acceptable is when calling a function that you happen to know never returns, but you lack type definitions that capture that. For a contrived example:

function raiseRangeErr(e: string): unknown {
    throw new RangeError(e);
}

function div(a: number, b: number): number {
    return b !== 0 ? a / b : raiseRangeErr("division by zero") as never;
}

Even then, it would be preferable to update your type definitions.

user3840170
  • 26,597
  • 4
  • 30
  • 62