TypeScript says that prop type is unknown despite my attempt to define my props strictly

Viewed 1171

I am new to Vue and even newer to TypeScript. I have researched docs for both and built small, small projects with them. However, moving into composition with Vue and TS is proving challenging.

I want to have 3 buttons reorganize the order of some jobs in a list, following a Net Ninja tutorial. However, even though Ive copied his code, TS is giving me errors in the IDE. Downstream (presumably it is a downstream issue from the errors showing in the ide) there is a bunch of code that isn't being reached. Let me show you.

<script lang="ts">
import { computed, defineComponent, PropType } from "vue";
import Job from "../types/Job";
import OrderTerm from "../types/OrderTerm";

export default defineComponent({
    props: {
        jobs: {
            required: true,
            type: Array as PropType<Job[]>,
        },
        order: {
            required: true,
            type: String as PropType<OrderTerm>,
        },
    },
    setup(props) {
        console.log("ce code est allerant", props, props.jobs);
        const aaa = props;
        const x = computed(() => {
            console.log(
                "this code was not reached; restated, it does not print, idk why"
            );
            return [...props.jobs].sort((a: Job, b: Job) => {
                return a[props.order] > b[props.order] ? 1 : -1;
            });
        });
        // console.log("fobar");
        return { x };
    },
});
</script>

I get this error in the IDE:

ype 'unknown' must have a '[Symbol.iterator]()' method that returns an iterator.Vetur(2488)
(parameter) props: Readonly<LooseRequired<Readonly<{
    jobs: unknown;
    order: unknown;
} & {}>>>

&

Type 'unknown' cannot be used as an index type.Vetur(2538)
(parameter) props: Readonly<LooseRequired<Readonly<{
    jobs: unknown;
    order: unknown;
} & {}>>>

I don't see how the jobs & order parts have been ill-defined. What could be wrong there? It looks just how it is in the Ninja's Code so... I am confused. The errors are a complete juxtaposition with my expectations, which is that the props I'm feeding in are detected by TS. they are correct.

Here's the contents of props.jobs prior to the computed() line:

Proxy { <target>: (4) […], <handler>: {…} }
​
<target>: Array(4) [ {…}, {…}, {…}, … ]
​​
0: Object { title: "bartender", location: "vancouver", salary: 35, … }
​​
1: Object { title: "priest", location: "Calgary", salary: 90, … }
​​
2: Object { title: "Farmworker", location: "Hyrule", salary: 40000, … }
​​
3: Object { title: "potus", location: "USA", salary: 999999, … }
​​
length: 4

If any useful context is MIA please let me know.

edit: hot on the trail, I changed it to computed((props) => ... and now I have a better error

TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'Job'.
    42 |            console.log("asdfsaf");
    43 |            return [...props.jobs].sort((a: Job, b: Job) => {
  > 44 |                return a[props.order] > b[props.order] ? 1 : -1;
       |                       ^^^^^^^^^^^^^^
    45 |            });
    46 |        });

edit to add my template sans the lorem ipsum:

<template>
    <div class="jobList">
        <h1>Ordered by: {{ order }}</h1>
        <ul>
            <li v-for="job in x" :key="job.id">
                <div class="card">
                    <div>{{ job.id }}</div>
                    <h2>{{ job.title }} in the city of {{ job.location }}</h2>
                    <p>{{ job.salary }} rupees</p>
                    <div class="description">
                        lorem ipsum but shorter
                    </div>
                </div>
            </li>
        </ul>
    </div>
</template>

Showing ../types/Job and ../types/OrderTerm:

// Job.ts
interface Job {
    title: string,
    location: string,
    salary: number,
    id: string,
    ft: boolean
}

export default Job
// OrderTerm.ts
type OrderTerm = "location" | "title" | "salary"

export default OrderTerm
1 Answers

you need to define the array as a Job array:

const jobs = [...props.jobs] as Job[]
Related